在C ++中调用Abstract Base类的构造函数

时间:2017-03-23 19:44:55

标签: c++ class c++11 inheritance constructor

我知道如果我有一个抽象类,那么我就无法创建一个抽象类类型的对象。但假设“Base”是基类,“Derived”是派生类。 在基类中,我有一个成员变量名。

Base.h
Base(string name = "");

Base.cpp
Base(string theName){name = theName);

这不是创造一个对象吗?

在Derived类中,我有成员变量年龄。 现在在派生类的默认构造函数

Derived.h
Derived(string name = "", int theAge = 0);

Derived.cpp
Derived(string theName, int theAge):Base(theName) { age = theAge }

这不是也调用了Base的默认构造函数吗? 那么,我是否可以调用参数化构造函数而不是默认构造函数?

还有一件事,如果我在Base类中除了pure函数之外还有另一个函数,如果不允许我为Base类创建一个对象,如何调用该函数?

提前致谢!

4 个答案:

答案 0 :(得分:3)

  

我知道如果我有一个抽象类,那么我就无法创建一个抽象类类型的对象。

有一个例外:抽象类的对象可以创建为派生类对象的子对象。

实际上,必须在那种情况下创建,因为这就是继承在C ++中的工作原理。派生类的对象包含基类的对象(或者通常是基类的对象,因为我们不要忘记C ++也支持多重继承)。

标准在§10.4/ 1中非常清楚地说明了这一点:

  

抽象类是一个只能用作其他类的基类的类;除了作为派生自它的类的子对象之外,不能创建抽象类的任何对象。

你有它:这个限制中可能存在抽象类的实例。因此,

Base(string theName){name = theName);
     

这不是创造一个对象吗?

它是一个像其他任何构造函数;它用于创建一个对象。鉴于上述规则,该类是抽象的这一事实并不重要。

Derived(string theName, int theAge):Base(theName) { age = theAge }
     

这不是也调用了Base的默认构造函数吗?

是的,是的。

  

那么,我是否可以调用参数化构造函数而不是默认构造函数?

所有参数默认为的构造函数是默认构造函数。

  

还有一件事,如果我在Base类中除了pure函数之外还有另一个函数,如果不允许我为Base类创建一个对象,如何调用该函数?

如果它是public函数,那么任何拥有派生类对象的人都可以调用它(这包括派生类本身)。此外,任何通过指针或对基类的引用访问派生类对象的人都可以调用它。当然,基类本身也可以调用它。

如果它是protected函数,则派生类和潜在的其他派生类可以调用它。

如果它是private,那么基类本身就可以调用它。

正如我们上面所建到的,您在技术上为基类创建了一个对象,作为派生类对象内的子对象。所以原则上,情况并不特殊,因为基类是抽象的。

这里要记住的是,定义了语言的技术性,以便所有基本的面向对象功能都能按预期工作。您不必在日常编程业务中担心这些事情。

答案 1 :(得分:1)

您正在混淆两个不同的概念:

  1. 构建对象。

  2. 实例化对象。

  3. 抽象类的构造与任何其他类一样。它可以有自己的自定义构造函数。或者它可以有一个默认构造函数,除非有某些条件禁止默认构造函数。

    无法实例化抽象类。正如你自己写的那样,你“无法创造”一个抽象类。您只能创建派生类(除非派生类也是抽象类)。

    创建派生类当然会创建并构造其所有基类。包括其基础抽象类。您的基类的构造函数(抽象类的构造函数)将很乐意履行其义务并构造基本抽象类。接下来,派生类将构造派生类,然后构造并实例化整个对象。

答案 2 :(得分:0)

  

这不是创造一个对象吗?

没有。它只是定义了如何构造对象。

  

还没有调用Base的默认构造函数吗?那么,我是否可以调用参数化构造函数而不是默认构造函数?

是的,它正在调用构造函数,但就像我上面所说的,Base(string theName){name = theName);,并没有调用任何东西。它只是一个构造函数定义。

  

还有一件事,如果我在Base类中除了pure函数之外还有另一个函数,如果不允许我为Base类创建一个对象,如何调用该函数?

您可以使用指向/引用派生类实例的基类的指针/引用来调用它。

答案 3 :(得分:0)

是的,如果你声明这样的构造函数,那么就不会生成默认的构造函数,因为编译器无法区分你想要调用的那个。例如,这段代码不会被编译,因为CL1(std :: string)是私有的,默认的CL1()不存在。

#include <iostream>
#include<string>
using namespace std;
class CL1{
    CL1(std::string s=""){
        std::cout<<" hello";
    }   
};
int main() {
    CL1 instance;
    return 0;
}