我知道如果我有一个抽象类,那么我就无法创建一个抽象类类型的对象。但假设“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类创建一个对象,如何调用该函数?
提前致谢!
答案 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)
您正在混淆两个不同的概念:
构建对象。
实例化对象。
抽象类的构造与任何其他类一样。它可以有自己的自定义构造函数。或者它可以有一个默认构造函数,除非有某些条件禁止默认构造函数。
无法实例化抽象类。正如你自己写的那样,你“无法创造”一个抽象类。您只能创建派生类(除非派生类也是抽象类)。
创建派生类当然会创建并构造其所有基类。包括其基础抽象类。您的基类的构造函数(抽象类的构造函数)将很乐意履行其义务并构造基本抽象类。接下来,派生类将构造派生类,然后构造并实例化整个对象。
答案 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;
}