简体   繁体   English

为什么基本构造函数会被继承,我该如何预防?

[英]Why are base Constructors inherited, How can i prevent it?

#include<iostream>
using namespace std;

int main(){
    class c1{
        public:
        c1(){
            cout<<"constructing c1";
        }

    };


    class c2:private c1{
        public:
        c2(){
            cout<<"constructing c2";
        }
    };
    c2 inst1;

}

q1. q1。 Even when the access is private, why is the base's c'tor called for derived object? 即使访问是私有的,为什么基地的指挥官也需要派生对象? ie why is c1() called even when class c1 is inherited as private? 即为什么即使类c1被继承为私有也为什么调用c1()

q2. q2。 Here c1 is inherited, how can i prevent that from happening? 在这里c1是继承的,我如何防止这种情况发生?

It's not inherited. 它不是继承的。 c2 is-a c1 . c2 c1 There's a c1 sub-object that is part of the c2 object. 有一个c1子对象是c2对象的一部分。

Any object needs to be constructed in order to be used, so the c2 constructor will call the c1 c'tor automatically (because it has no parameters, and can be used for default construction). 任何对象都需要构造才能使用,因此c2构造函数将自动调用c1 c'tor(因为它没有参数,并且可以用于默认构造)。

If you want further convincing that this happens, try adding a parameter to the c1 c'tor: 如果您想了解更多有说服力的,出现这种情况,请尝试将参数传递给c1 c'tor:

c1(int){
    cout<<"constructing c1";
}

Now it can't be used to default construct c1 . 现在它不能用于默认构造c1 You'll get a nice error, which can be resolved by explicitly calling the base class c'tor in c2 with some integer value: 您将得到一个不错的错误,可以通过使用一些整数值显式调用c2的基类c'tor来解决该错误:

c2() : c1(0) {
    cout<<"constructing c2";
}

This has nothing to do with private or public inheritance. 这与私有或公共继承无关。 Constructor of derived class are called after constructor of base class is called, destructors are called in reversed order. 派生类的构造函数在基类的构造函数被调用之后被调用,析构函数以相反的顺序被调用。

It's a fondamental key point of Object oriented programming 这是面向对象编程的基本要点

Here c1 in inherited, how can i prevent that from happening? 在继承c1的情况下,如何防止这种情况发生?

Short answer: You can't prevent it. 简短答案:您无法阻止。 Derived objects contain all parent objects as sub-objects, due to their inheritance. 由于继承,派生对象将所有父对象都包含为子对象。 So in order to initialize the object as a whole, the compiler has no choice but calling each constructor for every subobject. 因此,为了整体上初始化对象,编译器别无选择,只能为每个子对象调用每个构造函数。

You can however influence the behaviour of the parent's constructor by calling it with certain arguments. 但是,可以通过使用某些参数调用父构造函数的行为来影响它的行为。 Consider this: 考虑一下:

class Base {
    Data _data;
protected:
    Base(bool load_from_cache) {
        if(load_from_cache) _data = read_cache();
        else _data = read_database();
    }
};

class Derived : public Base {
public:
    Derived() : Base{ true } { } // specify from where to read the data
};

There are many other possibilities for injecting a custom behaviour, like passing function objects, lambdas, CRTP, you say it. 注入自定义行为还有很多其他可能性,例如传递函数对象,lambda,CRTP等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM