-
2021-10-21 17:55:18
题目为定义一个抽象基类B,并用它派生一个新类C,在C中实现抽象基类的纯虚函数接口;通过抽象基类的引用调用派生类的函数成员;在主函数中验证上述功能。
编写的代码如下:
#include <iostream> using namespace std; class B //声明抽象基类 { public: virtual void print() const = 0; //纯虚函数 }; class C : public B { public: virtual void print() //对虚函数进行再定义 !!!const必须要有 { cout << "通过抽象基类的引用调用派生类的函数成员" << endl; } }; int main() { C c; B &b =c; b.print(); return 0; }
认为程序已经正确,但是编译却报错:error C2259: 'C' : cannot instantiate abstract class due to following members,百度得出的结果是抽象基类的方法必须完全实现,对此很疑惑。
后来仔细检查发现是在C类中对纯虚函数进行再定义时函数漏写了const,应该为
virtual void print() const { ... }
改正后编译通过,于是来此记录一下。
派生类中的虚函数要保持其虚特征,必须与基类虚函数的函数原型完全相同,否则就是普通的重载函数,与基类的虚函数无关。
更多相关内容 -
在派生类的构造函数中调用基类的构造函数
2015-04-14 20:10:13《Visual C++2012入门经典(第6版)》实例,在派生类的构造函数中调用基类的构造函数 -
C++派生类中调用基类成员
2021-05-20 12:50:16基类和派生类具有相同成员时前面已经说明...下面例子中,基类和派生类都有成员变量“id”和成员函数“show()”,无论是在派生类的内部还是外部,直接调用的成员都是派生类的成员,而基类的成员函数show()未被调用。...基类和派生类具有相同成员时
前面已经说明了一旦继承之后,派生类就具有了基类的公有成员和保护成员,可以直接使用,在外部也可直接访问基类的公有成员。这一节要讲解的是如果基类和派生类具有相同名称的成员变量或可以成员函数时,如何区别使用。
下面例子中,基类和派生类都有成员变量“id”和成员函数“show()”,无论是在派生类的内部还是外部,直接调用的成员都是派生类的成员,而基类的成员函数show()未被调用。要调用基类成员,必须在成员函数名前加上范围(类名::),这也适用于基类的成员变量。
#include
#include
using namespace std;
class CBase {
string id;
string name;
public:
CBase(string s1, string s2) : name(s1), id("base-"+s2) { }
void show() {
cout << "name: " << name << endl;
cout << "id: " << id << endl;
}
};
class CDerive : public CBase {
string id;
int age;
public:
CDerive(string s1, int a, string s2) : age(a), id("DERIVE-"+s2), CBase(s1, s2) { }
void show() {
cout << "id: " << id << endl;
cout << "age: " << age << endl;
//派生类的内部调用基类的方法
CBase::show();
//show(); //如果误写成这样,将不断地重复循环地调用自身(即死循环)。
}
};
int main ( )
{
CDerive d("C语言中文网", 3, "8503026"); //派生类的实例
d.show(); //运行的是CDerive类的show()函数
cout << "-------------"<< endl;
//类的外部调用基类的方法
d.CBase::show(); //运行的是CBase类的show()函数
cout << "-------------"<< endl;
CBase b("C语言中文网", "8503026"); //基类当作普通类直接产生的实例
b.show(); //运行的是CBase类的show()函数
return 0;
}
运行结果:
id: DERIVE-8503026
age: 3
name: C语言中文网
id: base-8503026
-------------
name: C语言中文网
id: base-8503026
-------------
name: C语言中文网
id: base-8503026
多重继承的调用方法
多重继承时参数的调用方法和上面一样,只要在函数名前加上范围,调用成员变量也是一样。注意:要调用基类的成员变量时,要修改一下访问权限,不能为“private”。
#include
#include
using namespace std;
class CBase1 {
string name;
protected:
string id;
public:
CBase1(string s1, string s2) : name(s1), id("base1-"+s2) { }
void show() {
cout << "name: " << name << endl;
cout << "id: " << id << endl;
}
};
class CBase2 {
int salary;
protected:
string id;
public:
CBase2(int y, string s2) : salary(y), id("base2-"+s2) { }
void show() {
cout << "salary: " << salary << endl;
cout << "id: " << id << endl;
}
};
class CDerive : public CBase1, public CBase2 {
string id;
int age;
public:
CDerive(string s1, int a, string s2, int y)
: age(a), id("DERIVE-"+s2), CBase1(s1, s2), CBase2(y, s2) { }
void show() {
cout << "id: " << id << endl;
cout << "age: " << age << endl;
CBase1::show();
CBase2::show();
cout << "bas1: " << CBase1::id << endl; //调用CBase1的成员变量
cout << "bas2: " << CBase2::id << endl; //调用CBase2的成员变量
}
};
int main ( )
{
CDerive d("C语言中文网", 3, "8503026", 5000);
d.show();
return 0;
}
运行结果:
id: DERIVE-8503026
age: 3
name: C语言中文网
id: base1-8503026
salary: 5000
id: base2-8503026
bas1: base1-8503026
bas2: base2-8503026
删除派生类中的同名函数
上一个例子中,如果修改2个基类的show()函数的参数,在派生类或外部也一样不能直接调用,必须加上范围。下面,我们将派生类中的同名函数show()删除,是否会出错呢?
#include
#include
using namespace std;
class CBase1 {
string name;
string id;
public:
CBase1(string s1, string s2) : name(s1), id("base1-"+s2) { }
void show() {
cout << "name: " << name << endl;
cout << "id: " << id << endl;
}
};
class CBase2 {
int salary;
string id;
public:
CBase2(int y, string s2) : salary(y), id("base2-"+s2) { }
void show() {
cout << "salary: " << salary << endl;
cout << "id: " << id << endl;
}
};
class CDerive : public CBase1, public CBase2 {
string id;
int age;
public:
CDerive(string s1, int a, string s2, int y)
: age(a), id("DERIVE-"+s2), CBase1(s1, s2), CBase2(y, s2) { }
};
int main ( )
{
CDerive d("C语言中文网", 3, "8503026", 5000);
//d.show(); //编译出错,不知从哪个基类继承。
d.CBase1::show();
d.CBase2::show();
return 0;
}
运行结果:
name: C语言中文网
id: base1-8503026
salary: 5000
id: base2-8503026
-
第三十一节 C++ 继承之如何在派生类中调用基类被覆盖的函数成员(方法)
2018-04-08 18:21:55#include <iostream> using namespace std; /*有些基类的方法在派生...* 1: 直接在派生类中调用被覆盖的基类方法,如 Person::CheckPerson() ; * 2: 使用派生类对象调用被覆盖的基类方法,如 Tom.P...#include <iostream> using namespace std; /*有些基类的方法在派生类被覆盖,但有时我们需要调用基类的方法。 * 这里提供了两种方式去调用基类被覆盖的方法(均使用作用域解析运算符::)。 * 1: 直接在派生类中调用被覆盖的基类方法,如 Person::CheckPerson() ; * 2: 使用派生类对象调用被覆盖的基类方法,如 Tom.Person::CheckPerson(); */ class Person { protected: //只能在派生类内部访问protected成员,外部不可访问 bool man; public: // public权限,可被派生类访问 void CheckPerson(); Person(bool initValue) { //构造函数的重载,带初始值 man = initValue; cout << "Person constructor" << endl; } ~Person() { cout << "~Person deconstructor" << endl; } }; void Person::CheckPerson() { if (man) cout << "Person is man" << endl; else cout << "Person is woman" << endl; } class Man: public Person { //public继承,可访问基类public和protected权限的成员 public: void CheckPerson(); //覆盖基类的方法 Man() : Person(true) {}; //利用初始化列表,对基类的成员进行初始化(基类重载构造函数需要初始化值) ~Man() {}; }; /*类Man继承了Person的public和protected成员,这里覆盖基类中的函数CheckPerson()*/ void Man::CheckPerson() { //覆盖基类中的函数CheckPerson() if (man) { Person::CheckPerson();//使用作用域解运算符::,可调用被覆盖的基类方法 cout << "calss function is covered: man" << endl; } else { cout << "calss function is covered: woman" << endl; } } int main() { Man Tom; Tom.CheckPerson(); //派生类外部可调用继承的基类public成员 Tom.Person::CheckPerson(); //使用作用域解运算符::,可调用被覆盖的基类方法 //Tom.man = false; //编译出错,外部不可修改继承的protected成员 return 0; }
output:
Person constructor
Person is man
calss function is covered: man
Person is man
~Person deconstructor -
如何从派生类函数调用父类函数?
2020-01-09 14:17:27如何使用C ++从派生类调用父函数? 例如,我有一个名为parent的类,以及一个称为child的类,该类是从parent派生的。 每个类中都有一个print功能。 在定义孩子的打印功能时,如何使用C ++从派生类调用父函数? 例如,我有一个名为
parent
的类,以及一个称为child
的类,该类是从parent派生的。 每个类中都有一个print
功能。 在定义孩子的打印功能时,我想调用父母的打印功能。 我将如何去做呢?
#1楼
struct a{ int x; struct son{ a* _parent; void test(){ _parent->x=1; //success } }_son; }_a; int main(){ _a._son._parent=&_a; _a._son.test(); }
参考示例。
#2楼
如果基类成员函数的访问修饰符是受保护的或公共的,则可以从派生类中调用基类的成员函数。 可以从派生成员函数调用基类的非虚拟成员和虚拟成员函数。 请参考程序。
#include<iostream> using namespace std; class Parent { protected: virtual void fun(int i) { cout<<"Parent::fun functionality write here"<<endl; } void fun1(int i) { cout<<"Parent::fun1 functionality write here"<<endl; } void fun2() { cout<<"Parent::fun3 functionality write here"<<endl; } }; class Child:public Parent { public: virtual void fun(int i) { cout<<"Child::fun partial functionality write here"<<endl; Parent::fun(++i); Parent::fun2(); } void fun1(int i) { cout<<"Child::fun1 partial functionality write here"<<endl; Parent::fun1(++i); } }; int main() { Child d1; d1.fun(1); d1.fun1(2); return 0; }
输出:
$ g++ base_function_call_from_derived.cpp $ ./a.out Child::fun partial functionality write here Parent::fun functionality write here Parent::fun3 functionality write here Child::fun1 partial functionality write here Parent::fun1 functionality write here
#3楼
给定名为
Parent
父类和名为Child
子类,您可以执行以下操作:class Parent { public: virtual void print(int x); } class Child : public Parent { void print(int x) override; } void Parent::print(int x) { // some default behavior } void Child::print(int x) { // use Parent's print method; implicitly passes 'this' to Parent::print Parent::print(x); }
请注意,
Parent
是类的实际名称,而不是关键字。
#4楼
如果您的基类称为
Base
,而您的函数称为FooBar()
,则可以使用Base::FooBar()
直接调用它void Base::FooBar() { printf("in Base\n"); } void ChildOfBase::FooBar() { Base::FooBar(); }
#5楼
我冒着明显的危险:调用该函数,如果它在基类中定义,则该函数在派生类中自动可用(除非它是
private
)。如果派生类中有一个具有相同签名的函数,则可以通过添加基类的名称以及两个冒号
base_class::foo(...)
来消除歧义。 你应该注意到,不像Java和C#,C ++ 不具备“基础类”(关键字super
或base
,因为C ++的支持), 多重继承 ,这可能导致歧义。class left { public: void foo(); }; class right { public: void foo(); }; class bottom : public left, public right { public: void foo() { //base::foo();// ambiguous left::foo(); right::foo(); // and when foo() is not called for 'this': bottom b; b.left::foo(); // calls b.foo() from 'left' b.right::foo(); // call b.foo() from 'right' } };
顺便说一句,您不能两次直接从同一个类派生,因为将无法在另一个基础类上引用一个基础类。
class bottom : public left, public left { // Illegal };
#6楼
使用父范围解析运算符调用父方法。
父类:: method()
class Primate { public: void whatAmI(){ cout << "I am of Primate order"; } }; class Human : public Primate{ public: void whatAmI(){ cout << "I am of Human species"; } void whatIsMyOrder(){ Primate::whatAmI(); // <-- SCOPE RESOLUTION OPERATOR } };
#7楼
在MSVC中,有一个针对此的Microsoft特定关键字: __super
MSDN:允许您明确声明正在为要重写的功能调用基类实现。
// deriv_super.cpp // compile with: /c struct B1 { void mf(int) {} }; struct B2 { void mf(short) {} void mf(char) {} }; struct D : B1, B2 { void mf(short) { __super::mf(1); // Calls B1::mf(int) __super::mf('s'); // Calls B2::mf(char) } };
-
C++派生类中与基类同名函数的调用问题
2016-11-11 22:26:14一、派生类,即子类中的函数与基类的函数的情况有以下三种。 1、不是同名函数 2、函数名相同,形参的个数或类型不同。 3、函数名相同,形参的个数和类型也相同。 二、接下来就这三种情况探讨子类调用基类函数的... -
继承与派生(Part Ⅱ)——派生类的构造函数/析构函数
2022-01-14 18:45:01但有一点与私有成员不同,保护成员可以被派生类的成员函数引用。 如果基类声明了私有成员,那么任何派生类都是不能访问它们的,若希望在派生类中能访问它们,应当把它们声明为保护成员。如果在一个类中声明了保护... -
C++基类与派生类中同名成员的调用
2017-09-07 20:10:50实例: #include using namespace std; class parent { public: void print(void) ... cout << "parent a=:"<<a; } public: int a; private: int b; protected: int d; }; class child3 : public parent -
C++--派生类中的默认成员函数
2021-04-25 10:34:46派生类中的默认成员函数2. 继承与友元、静态成员 1. 派生类中的默认成员函数 6个默认成员函数:构造函数、析构函数、拷贝构造函数、赋值重载、取地址重载(普通对象和const对象取地址) 派生类的构造函数必须... -
【C++】(二十七)派生类成员的访问 |派生类的构造和析构函数
2020-11-04 19:43:28文章目录派生类成员的访问1 类的保护成员2 派生类成员的访问权限3 赋值兼容规则派生类的构造和析构函数1 派生类的构造函数1.1 派生类构造函数的定义1.2 组合关系的派生类的构造函数2 派生类的析构函数 派生类成员的... -
MFC中非类成员函数调用类成员函数方法
2018-10-09 14:39:041、定义对话框类对象全局变量指针 CDialog *g_pDlg,...如果想在B中调用A的成员函数,该怎么办呢? 方法一: 在类B的cpp文件中包含A类的头文件,然后在B的需要调用A的函数的函数中,添加 #include "A.h"... -
C++中通过派生类调用第二基类的普通成员函数时this指针的调整
2017-05-26 21:28:48我们都知道,C++编译器对于普通的类成员函数的编译,会将其编译成非成员函数,即普通全局函数,并且对函数名进行name-mangling,加入this指针作为该函数的第一参数,这个this指针的类型是本类类型 即 class A { ... -
为什么在删除派生类对象时调用基类析构函数(虚拟)?
2021-03-08 19:50:50Constructor and destructor are different from the rest of regular methods.Constructor不能是虚拟的在派生类中,您要么显式调用基类的构造函数或者,如果你没有调用基类构造函数编译器将插入调用 . 它将调用不带... -
派生类的构造函数和析构函数的调用顺序
2019-04-23 09:38:35通常情况下: 当创建派生类对象时: 基类的构造函数——>派生类的构造函数;...1.派生类的构造函数和析构函数的调用顺序 (1) 输出的是:基类的构造函数 基类的构造函数 派生类的构造函数 输出... -
派生类的构造函数和析构函数
2021-04-29 16:13:16因此,对继承的基类成员初始化的工作要由派生类的构造函数承担,同时基类的析构函数也要被派生类的析构函数来调用 1.派生类构造函数的定义 在执行派生类的构造函数时,使派生类的数据成员和基类的数据成员同时都被... -
继承(隐藏 & 派生类的六个默认成员函数)
2018-07-17 16:11:24隐藏是指:在基类和派生类中有同名的成员变量或成员函数,那么派生类的成员变量、成员函数就将基类的隐藏(重定义)了。 如何调用隐藏的成员函数(或使用隐藏的成员变量)? 指定作用域 2 派生类的六个默认... -
C++中基类与派生类的构造函数和析构函数
2019-04-11 10:40:041.Cpp中的基类与派生类的构造函数 基类的成员函数可以被继承,可以通过派生类的对象访问,但这仅仅指的是普通的成员函数,类的构造函数不能被继承。构造函数不能被继承是有道理的,因为即使继承了,它的名字和派生... -
【C++】4.2 派生类与继承 - 派生类的构造函数和析构函数
2019-09-09 16:38:13(1)基类的构造函数和析构函数不能被继承,在派生类中,如果对派生类新增成员进行初始化,就必须加入派生类构造函数 (2)从基类继承的成员仍有基类的构造函数完成 (3)但需要在派生类构造函数中对基类的构造... -
C++继承与派生:派生类中对基类成员的重定义
2020-03-31 16:15:57派生类中对基类成员的重定义 重定义的理解 重定义成员的访问 重定义的理解 重定义: 在派生类中可定义与基类成员同名的成员(可以是成员变量也可以是成员函数),此时在派生类中有两个同名的成员。 同名成员: 同名... -
C++中的派生类对基类成员的访问问题
2021-12-03 19:17:36C++中派生类对基类成员的访问形式主要有以下两种: 1、内部访问:由派生类中新增成员对基类继承来的成员的访问。 2、对象访问:在派生类外部,通过派生类的对象对从...基类的private成员在私有派生类中是不可直接访问的 -
【C++】 派生类的默认成员函数
2020-03-27 16:29:466个默认成员函数,“默认”的意思就是指我们不写,编译器会变成我们自动生成一个,那么在派生类中,这几个成员函数是如何生成的呢? 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类... -
C++第五章(类的继承派生)下篇(派生类的构造函数和析构函数)
2018-12-01 22:58:33派生类的构造函数和析构函数 为什么会有派生类的构造...所以在设计派生类的构造函数时,不仅要考虑派生类所增加的数据成员,还要考虑基类成员的初始化。也就是说,希望在执行派生类构造函数时,使派生类的数据... -
创建派生类对象时,构造函数的执行顺序是什么
2021-02-12 23:01:17创建派生类对象时,构造函数的执行顺序是:基类构造函数、派生类对象成员构造函数、派生类本身的构造函数。对象创建时,代码的加载顺序是:静态代码、非静态代码、构造方法。创建派生类对象时,构造函数的执行顺序是... -
C++:派生类构造函数
2021-01-21 21:17:50如果派生类有自己新增的成员,且需要通过构造函数初始化,则派生类要自定义构造函数。 若不继承基类的构造函数 派生类新增成员:派生类定义构造函数初始化; 继承来的成员:自动调用基类构造函数进行初始化; ... -
C++派生类构造函数和析构函数的调用顺序
2020-05-08 15:07:17派生类构造函数的调用顺序: 基类的构造函数(如果有多个基类,按照基类的声明顺序来构造,声明顺序也就是class C:冒号后面这个顺序);该派生类的成员变量的声明顺序;该派生类自身的构造函数 派生类析构的顺序:... -
C/C++中为什么在类外利用多态基类指向派生类指针可以调用类的私有成员函数?
2013-09-28 11:42:09class A { protected: A(){} ~A(){} public: virtual void print() { cout } }; class B:public A { public: B(){} ~B(){} private: virtual void print() { cout } } -
第三十二节 C++ 继承之基类的成员函数在派生类中被隐藏
2018-04-08 18:42:46/*假设基类中函数被重载,当派生类覆盖基类的成员函数时,会隐藏到基类的其他的重载函数 * 注:应该尽量避免隐藏基类的成员函数 */ class Person { protected: //只能在派生类内部访问protected成员,外部不可访问 ... -
C++之常引用对象只能调用常成员函数、重载为成员函数和友元函数的区别
2020-05-16 18:18:30设计一个CShape抽象类,类中包含纯虚函数 从CShape类派生出三角形类CTriangle、矩形类CRectangle和椭圆类CEllipse 使用一个公共接口计算三角形对象、矩形对象和椭圆对象的面积 重载运算符>用于判断两个... -
c++ 继承 及 派生类的默认成员函数解析
2018-09-07 21:06:07在编写大型程序时,往往有很多的类,每个类都有自己的成员变量和成员函数,但有些类之间的数据成员和函数却相同,为了节省代码量和工作时间,只需继承父类中的数据成员和函数即可。 有了继承,继承对象可以使用被... -
有子对象的派生类的构造函数和析构函数的调用
2019-07-18 23:58:12{派生类中新增数据成员的初始化语句} 执行派生类构造函数的顺序是: (1)先调用基类的构造函数,对基类数据成员进行初始化 (2)调用子对象的构造函数,对子对象数据成员进行初始化 (3)最后执行派生类构造...