[C++ Primer] C15 关于c++的继承,你需要知道的一些知识

本文介绍了C++中的面向对象编程概念,包括数据抽象、继承和动态绑定。动态绑定允许我们在运行时选择函数的版本。文章详细讨论了基类和派生类的关系,虚拟函数和纯虚函数的作用,以及构造函数和析构函数在继承链中的使用。还提到了抽象类不能被实例化,以及如何处理继承和容器的兼容性问题,如对象切片问题及解决方案。最后强调了基类通常应定义虚析构函数以避免内存泄漏。

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

  1. constrructor: base -> derived class
  2. destructor: derived -> bass class
  3. override: let compiler help check whether the override success.
  4. 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.)
  5. 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

  1. namespace qualifier: when we want to use the func from the parent class not the derived class.
  2. 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

  1. protected can be access by child class, can only be accessed inside the clas!
  2. 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

  1. 在类内寻找
  2. 找不到就往上一级寻找

static type -> dynamic type

15.7 Constructors and Copy Control

  1. 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则不会被销毁,这样会导致内存泄露,所以我们需要在基类写一个虚析构函数,让他自行决定调用哪一个派生类的析构函数!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值