기본적으로 C++는 함수에 객체를 전달할 때 C와 똑같이 값에 의한 전달을 사용한다. 특별히 따러 지정해주지 않은 한은 "사본"을 쓴다는 것이다. 하지만 여기서 "사본"을 쓸 때 문제가 생긴다. 첫 번째로는 연산을 쓸 때 없이 증가시킬 수도 있다는 것이다. 다음 코드를 봐보자
class Person
{
private:
string name;
string address;
public:
Person() {}
virtual ~Person() {}
};
class Student : public Person
{
private:
string schoolName;
string schoolAddress;
public:
Student() {}
~Student() {}
};
bool validateStudent(Student s); //Student를 값으로 전달받는 함수
Student plato;
int _tmain()
{
bool platoIsOK = validateStudent(plato);//함수 호출
}
valilateStudent 함수를 값에 의한 전달을 이용하여 함수호출 시 각 각 6번의 생성자와 소멸자의 호출이 쓸 때 없이 이뤄졌다.(name,address,person,schoolname,schooladdress,student)소멸자도 똑같다.
왜 이렇게 되냐면은 아까 말했듯이 "사본"을 쓴다고 했다. 그렇다면 함수의 매개변수에 넘겨진 객체와 똑같은 값을 가진 "또 다른" 객체가 새로 만들어지는 것이다. 그러기에 당연하게도 기본 클래스와 상속클래스, 그리고 그 안에 있는 객체들까지 해서 생성자가 6번 일어나는 것이다.(클래스를 사용하려면 그 해당 클래스 객체는 반드시"생성자"를 이용하여 초기화를 해야 한다는 것을 잊지 말자.) 이 쓸모없는 연산 행위를 해결할 수 있는 간단한 방법이 있다. 참조자를 쓰는 것이다.
bool validateStudent(const Student& s);
이렇게 하면 위와같은 쓸데없는 연산 행위도 막을 수 있고 또 한 가지의 문제점을 막을 수 있다. 그 문제점이란 복사 손실 문제이다. 다음 코드를 봐보자
class TEST
{
public:
virtual void ClassFunc() const
{
cout << "Test" << endl;
}
};
class SubTest : public TEST
{
public:
virtual void ClassFunc() const
{
cout<<"Test2"<<endl;
}
};
void TestFunc(TEST t) //밑에 TEST2부분이 잘려나감
{
t.ClassFunc();
}
int main()
{
SubTest t;
TestFunc(t); //문제 발생!
}
위 코드에서 TestFunc 함수를 호출하면 복사손실문제가 발생한다. SubTest부분이 날라가버린다는것이다. 그 증거로 virtual 함수인 ClassFunc함수를 호출하면 SubTest의 ClassFunc함수가 아닌 TEST의 TestFunc함수가 호출된다.
하지만 이것도 아까 말했듯이 &참조자를 붙여주는것으로 해결할 수 있다.
이것만은 잊지 말자!
1."값에 의한 전달" 보다는 "상수 객체 참조자에 의한 전달"을 선호한다. 대체적으로 효율적일뿐만 아니라 복사손실 문제까지 막아준다.
2. 이번 항목에서 다룬 법칙은 기본제공 타입 및 STL 반복자, 그리고 함수 객체 타입에는 맞지 않는다.. 이들에 대해서는 "값에 의한 전달"이 더 적절하다.