The document discusses inheritance and polymorphism in C++. It shows examples of defining base and derived classes, and using virtual functions to allow polymorphic behavior. It also covers issues that can arise from multiple inheritance like ambiguous function calls, and ways to resolve them like using virtual inheritance or explicitly calling the base class function. Dynamic casting is demonstrated to check an object's type at runtime.
10. 10
class Dog {
public:
virtual void bark() { cout << "Woof!" << endl; }
virtual void eat() { cout << "The dog has eaten." << endl; }
};
class Bird {
public:
virtual void chirp() { cout << "Chirp!" << endl; }
virtual void eat() { cout << "The bird has eaten." << endl; }
};
11. 11
DogBird confusedAnimal;
confusedAnimal.eat();
error C2385: ambiguous access of 'eat'
note: could be the 'eat' in base 'Dog'
note: or could be the 'eat' in base 'Bird'
static_cast<Dog>(confusedAnimal).eat(); // 슬라이싱, Dog::eat() 호출
confusedAnimal.Dog::eat(); // 명시적으로 Dog::eat() 호출
void DogBird::eat()
{
Dog::eat(); // 명시적으로 Dog의 eat() 호출
}
12. 12
class Dog
{
public:
virtual void eat()
{
cout << "The bird has eaten." << endl;
}
};
class Bird : public Dog {};
class DogBird : public Bird, public Dog {};
DogBird confusedAnimal;
confusedAnimal.eat();
error C2385: ambiguous access of 'eat'
note: could be the 'eat' in base 'Dog'
note: or could be the 'eat' in base 'Dog'
13. 13
class Animal
{
public:
virtual void sleep() { cout << "Zzz..." << endl; }
};
class Dog : public Animal { … };
class Bird : public Animal { … };
confusedAnimal.sleep();
error C2385: ambiguous access of 'sleep'
note: could be the 'sleep' in base 'Animal'
note: or could be the 'sleep' in base 'Animal
14. 14
class Animal {
public:
virtual void sleep() = 0;
};
class Dog : public Animal {
public:
virtual void sleep() { … }
};
class Bird : public Animal {
public:
virtual void sleep() { … }
};
class DogBird : public Dog, public Bird {
public:
virtual void sleep() { Dog::sleep(); }
};
15. 15
class Animal
{
public:
virtual void sleep() { cout << "Zzz..." << endl; }
};
class Dog : public virtual Animal { … };
class Bird : public virtual Animal { … };
confusedAnimal.sleep(); // Animal이 virtual이기 때문에 모호하지 않음
16.
17. 17
class Super
{
public:
void go() { cout << "Super::go()" << endl; }
};
class Sub : public Super
{
public:
void go() { cout << "Sub::go()" << endl; }
};
Sub mySub;
mySub.go();
Sub::go()
Sub mySub;
Super& ref;
ref = mySub;
ref.go();
Super::go()
21. 21
class Super {
public:
Super() { }
~Super() { }
};
class Sub : public Super {
private:
char* mString;
public:
Sub() { mString = new char[30]; }
~Sub() { delete[] mString; }
};
Super* ptr = new Sub(); // mString은 이 시점에 할당됨
delete ptr; // ~Super가 호출되었지만
// virtual이 아니기 때문에
// ~Sub는 호출되지 않음
24. 24
참고 : http://prostars.net/55
#include <iostream>
using namespace std;
class Base
{
public:
virtual void print() { cout << "Base" << endl; }
};
class Derived : public Base
{
public:
virtual void print() { cout << "Derived" << endl; }
};
25. 25
참고 : http://prostars.net/55
Base* base1 = new Base;
Base* base2 = new Derived;
Derived* derived1 = new Derived;
Derived* derived2 = nullptr;
// 컴파일 오류 : 타입 변환을 할 수 없다.
// derived2 = base1;
// 컴파일 성공 : 런타임에 타입 변환에 실패하며
// nullptr을 반환한다.
derived2 = dynamic_cast<Derived*>(base1);
if (derived2 == nullptr)
cout << "Runtime Error" << endl;
26. 26
참고 : http://prostars.net/55
// 컴파일 오류 : 타입 변환을 할 수 없다.
// derived2 = base2;
// 컴파일 성공 : 런타임에 타입 변환에 성공하며
// Derived 타입의 포인터를 반환한다.
derived2 = dynamic_cast<Derived*>(base2);
if (derived2)
derived2->print();
// 컴파일 성공 : 이런 경우에는 캐스팅이 필요 없다.
derived2 = derived1;
27. 27
#include <iostream>
#include <typeinfo>
using namespace std;
class Animal
{
virtual void something() { }
};
class Dog : public Animal { };
class Bird : public Animal { };
void speak(const Animal& animal) {
if (typeid(animal) == typeid(Dog&))
cout << "Woof!" << endl;
else if (typeid(animal) == typeid(Bird&))
cout << "Chirp!" << endl;
}
Dog dog;
Bird bird;
Animal& animal = dog;
speak(animal);
animal = bird;
speak(bird);
Woof!
Chirp!