C15 OOP
Overview:
key ideas of OOP are data abstractions, inheritance, and dynamic binding.
Inheritance:
base class defines members that are common to the types in the hierarchy.
base class defines as virtual those functions it expects its derived classes to define for themselves. (纯虚函数)
// parent class
class book {
public:
int a;
virtual void func()=0; // pure virtual func
};
// B is the deriverd class of A
class comicBook : public book {
public:
// dynamic binding 动态绑定
// we can use the same code to process objects of parent and child interchangeably.
void func() override{
cout << "I'm the comic book!" << endl;
}
};
class actionBook : public book {
public:
void func() override{
cout << "I'm the action book!" << endl;
}
};
int main() {
comicBook cb;
actionBook ab;
cb.func(); // I'm the comic book!
ab.func(); // I'm the action book!
book* b1 = (book*) &cb;
b1->func(); // I'm the comic book!
book& b2 = ab;
b2.func(); // I'm the action book!
return 0;
}
dynamic binding is known as run-time binding, because we don’t know which type of the func will be chosen until run time!
15.2 Define base and derived class
- constrructor: base -> derived class
- destructor: derived -> bass class
- override: let compiler help check whether the override success.
- explanation about: book& b2 = ab; compiler will detect static type, that is whether the base class define the virtual func/ pure virtual func. Then it will convert it to dynamic type, that is how the virtual func is defined in the derived class. (书中原话:When we call a virtual function through a pointer or reference, the call will be dynamically bound.)
- Why should we use “: public book”? 书中原话:When the derivation is public, the public members of the base class become part of the interface of the derived class as well.
-
Base classes ordinarily should define a virtual destructor. Virtual destructors are needed even if they do no work.
-
prevent inheritance: we can prevent a class from being used as a base by following the class name with final
class A final{
}; // A cannot be derived
15.3 virtual function
- namespace qualifier: when we want to use the func from the parent class not the derived class.
- A function that is virtual in a base class is implicitly virtual in its derived classes. When a derived class overrides a virtual, the parameters in the base and derived classes must match exactly.
b2.actionBook::func(); // notice that actionBook's func cannot be a pure virtual func!
15.4 Abstract class
cannot be instantiate! 不能被实例化
eg: pure virtual function
15.5 Access control
- protected can be access by child class, can only be accessed inside the clas!
- friend class can access protected and public
difference between struct and class:
default private and default public
15.6 Class Scope under Inheritance
name lookup | name resolvation
- 在类内寻找
- 找不到就往上一级寻找
static type -> dynamic type
15.7 Constructors and Copy Control
- virtual destructor in base class: 每一个类做好自己的事情
class A {
public:
int* a_;
A(int a) : a_(&a){
cout << "construct base A" << endl;
}
virtual ~A() {
// delete a_;
cout << "destruct base A" << endl;
}
};
class B : public A {
public:
int* b_;
B(int a, int b) : A(a), b_(&b) {
cout << "construct derived B" << endl;
}
~B() {
// delete b_;
// delete a; // a need to be deleted in base class
cout << "destruct derived B" << endl;
}
};
int main() {
B b(1,2);
return 0;
}
construct base A
construct derived B
destruct derived B
destruct base A
15.8 Containers and Inheritance
当衍生类放进基类的容器中时,会被砍掉多余的部分!
书中原话:Because derived objects are “sliced down” when assigned to a base-type object, containers and types related by inheritance do not mix well.
vector<A> vec;
vec.push_back(A(1));
vec.push_back(B(1,2));
// slice down!
cout << vec[1].b_ << endl; // error
sol: put pointer not onject!传入指针可以解决slice down问题
vector<A*> vec;
vec.push_back(&A(1));
vec.push_back(&B(1,2));
B* b = (B*)vec[1];
cout << b->b_ << endl;
chapter summary
Inheritance
Dynamic binding: choose which version of func at run time!
Dynamic binding applies only to functions declared as virtual and called through a reference or pointer.
Base classes usually should define a virtual destructor even if the class otherwise has no need for a destructor.
说明:当一个基类指针指向一个派生类时,当基类指针被销毁时,如果没有virtual,则会销毁基类的member,派生类新增的member则不会被销毁,这样会导致内存泄露,所以我们需要在基类写一个虚析构函数,让他自行决定调用哪一个派生类的析构函数!
本文介绍了C++中的面向对象编程概念,包括数据抽象、继承和动态绑定。动态绑定允许我们在运行时选择函数的版本。文章详细讨论了基类和派生类的关系,虚拟函数和纯虚函数的作用,以及构造函数和析构函数在继承链中的使用。还提到了抽象类不能被实例化,以及如何处理继承和容器的兼容性问题,如对象切片问题及解决方案。最后强调了基类通常应定义虚析构函数以避免内存泄漏。
919

被折叠的 条评论
为什么被折叠?



