C++에서 헷갈리거나 중요한 것을 정리한 것입니다.
멤버 변수
Cat* myCat = new Cat(5, "Nabi");
Cat* yourCat = new Cat(2, "Jerry");
멤버 함수
멤버함수 동작 예시
myCat->GetName();
yourCat->GetName();
GetName()
함수를 호출하게 된다....
int GetAge(Animal* ptr) const
{
return ptr->mAge;
}
...
const char* GetName(Cat* ptr) const
{
return ptr->mName;
}
...
정적 바인딩
정적 바인딩 예시 코드
//Animal.h
class Animal
{
public:
int GetAge();
void speak() const; //"animal" 출력
private:
int mAge;
};
//Cat.h
class Cat: public Animal
{
public:
const char* GetName();
void speak() const; //"cat" 출력
private:
char* mName;
}
//main.cpp
int main()
{
Cat* cat = new Cat();
Animal* animalCat = new Cat();
//멤버 함수는 컴파일 시에 딱 한번만 메모리에 할당 (같은 공간을 차지)
cat->speak(); //"cat" 출력
animalCat->speak(); //"animal" 출력
}
정적 바인딩 동작 예시
아래의 코드를 실행했을 때
Cat* myCat = new Cat();
myCat->Speak(); //아래 어셈블리 코드에서 아래 Speak() 호출
Animal* yourCat = new Cat();
yourCat->Speak(); //아래 어셈블리 코드에서 위 Speak() 호출
어셈블리 코드
void Speak(Animal* ptr) const { //생략 }
void Speak(Cat* ptr) const { //생략 }
class Animal
{
public:
//생성자 생략
virtual void Speak() const //virtual 키워드!!
{
cout << "Animal" << endl;
}
};
class Cat :public Animal
{
public:
//생성자 생략
void Speak() const
{
cout << "Meow" << endl;
}
};
int main()
{
Cat* myCat = new Cat(2, "Jerry");
Animal* yourCat = new Cat(5, "Nabi");
myCat->Speak(); // Meow
youtCat->Speak(); //Meow
}
Animal* myAnimal = new Cat(5, "Jerry");
처럼 개체를 생성하고 delete myAnimal
을 할 경우 ~Animal()
만 호출되기 때문에 mName
이라는 힙에 할당한 변수를 메모리에서 해제하지 못해서 메모리 누수가 발생한다.class Animal
{
public:
virtual ~Animal();
//~Animal(); 소멸자의 정적 바인딩 -> 메모리 누수 발생
private:
int mAge;
};
class Cat :public Animal
{
public:
virtual ~Cat(); //virtual 안써도 되지만 쓰는 습관
private:
char* mName;
};
Cat::~Cat()
{
delete mName;
}
int main()
{
Cat* myCat = new Cat(2, "Nabi");
delete myCat; //->~Cat() 호출
//->~Animal() 호출
Animal* myAnimal = new Cat(5, "Jerry");
delete myAnimal; //소멸자에 virtual 키워드 없을 때
//~Animal()만 호출된다.
}
Animal myAnimal1;
-> 불가능Animal* myAnimal2 = new Animal();
-> 불가능Animal* myCat = new Cat();
-> 가능Animal& myCatRef = *myCat;
-> 가능virtual <반환타입> <함수명> = 0;
class IFlyable //인터페이스 클래스
{
public:
virtual void Fly() = 0;
};
class IWalkable
{
public:
virtual void Walk() = 0;
};
class Bat :public IFlyable, public IWalkable
{
public:
void Fly()
{
//구현
}
void Walk()
{
//구현
}
};