当基类构造函数受到保护时,在派生类成员函数中创建基类实例

时间:2015-04-29 18:22:27

标签: c++ constructor protected base derived

给出以下代码:

class A
{
protected:
    A(){};  // compilation error
public:
    void foo(){cout << "A\n";}; 
};

class B : public A
{
public:
    B() { };
    void foo(){
        cout << "B\n";
        A A(); // OK
        A a1; // compilation error
    }
};

如果我将基类A构造函数更改为public,则代码将编译。怎么解释这个?

3 个答案:

答案 0 :(得分:2)

为了创建一个对象,必须可以访问所需的构造函数。在B的成员中,您可以通过A类型的对象访问B的受保护成员,但。因此,您无法访问受保护的默认构造函数。

前一行A a();编译,因为它声明了一个函数。

答案 1 :(得分:0)

要允许访问受保护的方法,您可以使用friend class。 一个例子:

class A
{
    friend class B;
protected:
    A(){};
public:
    void foo(){cout << "A\n";}; 
};

class B : public A
{
public:
    B() { };
    void foo(){
        cout << "B\n";
        A a1;
    }
};

答案 2 :(得分:0)

如果您有任何具有受保护或私有构造函数的类,则该类被视为“抽象类对象”这意味着它表示对象应包含所有注释元素的概念或概念。您无法直接实例化此类型的对象!因此,您必须从此类继承谁的构造函数是公共的,除非它们也是抽象的。另一个想法是成为一个专门的对象,不能直接实例化,但可以成为其他类的朋友,他们的方法可以实例化对象,这意味着那些有朋友访问这个抽象类的类将能够实例化这个对象,生活在朋友类对象的生命范围和范围内。例子:

class A {
public: 
    enum ClassType {
        TYPE_A = 0,
        TYPE_B,
        TYPE_C,
        TYPE_D,
        TYPE_E,
        TYPE_F
    };

private:
    unsigned m_uId;
protected:
    explicit A( A::ClassType type ) :
    m_uId( static_cast<unsigned>( type ) {}

    void initialize() = 0; // Purely Abstract - Each Derived Class Must Create This Function
    void cleanup();     
};

class B sealed : public A {
public:
    B() : A( TYPE_A ) {}
    void initialize() override; 
};

class C sealed : public A {
public:
    C() : A( TYPE_C ) {}
    void initialize() override;
};

class D : public A {
protected:
    D( A::ClassType type ) : A( type ) {}          
    void initialize() override = 0;
};

class E sealed : public D {
public:
    E() : D( TYPE_E ) {}
    void initialize() override;
};

class F sealed : public D {
public:
    F : D( TYPE_F ) {}
    void initialize() override;
};

这里我演示了多态继承。 A级和A级D你无法实例化对象,但是B,C,E和B类。你可以实例化对象。因为A&amp; A的构造者D受到保护,任何派生类都可以访问它们。使用此设置,每个类都可以访问A :: cleanup(),并且每个类都必须实现自己的:: initialize()覆盖函数。

对于下一部分,我将演示如何使用友元类可以使用的抽象类。

class Counter {
    friend unsigned Object1::getCount();
    friend unsigned Object2::getCount();
private:
   static unsigned m_uCounter;       
   Counter() { ++m_uCounter; }

public:
    unsigned getCounter() { return m_uCounter; }       
};

class Object1 {
    friend class Counter;
private:
    unsigned m_uCount;
public:
    Object1() : m_uCount( 0 ) {}
    void count() { 
        Counter counter; 
        m_uCount = counter.getCounter();
    }

    unsigned getCount() const { return m_uCounter; }      
};

class Object2 {
    friend class Counter;
private:
    unsigned m_uCount;
public:
    Object2() : m_uCount( 0 ) {}
    void count() {
        Counter counter;
        m_uCount = counter.getCounter();
    }

    unsigned getCount() const { return m_uCount; }
};

此代码显示如何使用不能单独声明的抽象类,但可以通过作为友元类在其他类中使用。在这种情况下,作为一个示范,Counter类的唯一目的是进行递增的工作。计数器类不能是一个没有意义的独立对象,但是它通过友元声明在其他类中的使用允许这些类通过声明来自外部类的函数声明来访问其构造函数。抽象类中的友元函数。这种设置只允许Object1 :: getCount()和Object2 :: getCount()声明一种Counter类型并且可以访问Counter :: getCounter()。

我希望这有助于您理解使用继承处理多态性的抽象类,通过朋友使用的抽象类关联,以及如何正确声明抽象类型。

在你的代码中,其他人已经解决了A A();正在声明一个函数原型,其中A a1;正在尝试声明一种抽象的A类型。