C++ 调用基类方法
本文将讨论使用 C++ 从子类调用父类方法。 首先,我们将快速刷新继承。
稍后我们将讨论不同场景下调用基类方法以及相关问题。
C++ 中的继承
继承是面向对象编程的一个强大功能。 通过继承,子类可以共享父类的属性和函数,从而促进 OOP 中的可重用性。
在继承中,两个类形成一种称为“父子”、“基础-派生”或“通用-专业”关系的关系; 然而,最常采用的是源自基础的术语,而不是父项和子项。
C++中继承的语法:
class Parent{..};
class Child: InheritanceSpecifier Parent{...};
要创建派生类,我们必须编写 InheritanceSpecifier,后跟基类的名称。 此处,InheritanceSpecifier 可以是公共的、私有的或受保护的。
而且,如果继承时指定了多个父类的名称,则可以是多重继承。 有关继承类型的更多信息可以在这里找到。
为了让事情变得简单,我们将在整篇文章中使用公共继承。 我们可以在子类中并使用子类的对象调用基类方法(如果不是私有的),如下面的代码所示。
class P{
public:
void pf(){ cout << "Parent class function\n";}
};
class C: public P{
public:
void cf(){
pf();
cout <<"Child class function\n";
}
};
int main(){
C cObj;
cObj.cf();
cObj.pf();
return 0;
}
我们创建了一个父类 P,它是从子类 C 公开继承的。子类 C 中的 cf() 函数调用基方法 pf()。
类似地,在驱动程序代码(即main())中,子对象cObj直接调用基类方法。
输出:
Parent class function
Child class function
Parent class function
上面的例子对于理解基类函数的调用非常简单:在子类中以及子类的对象中。
但是,更复杂的情况在调用基本方法时可能需要额外小心,如以下段落中所述。
调用基类方法时的问题
前面的代码和输出中调用基类方法似乎没有问题。 但是,会出现一些相关的问题,例如父类和子类是否具有相同的功能,或者子类有两个或多个具有相同功能的父类。
我们来一一讨论这些问题。
父母和孩子有相同的功能
父类和子类可能具有相同的功能,并且在某些情况下,我们可能希望用子类对象来调用父类函数,或者我们可能希望在子类内部调用父类函数。
首先,让我们看一下演示该场景的代码。
class Parent{
public:
void f(){ cout << "Parent class function\n"; }
};
class Child: public Parent{
public:
void f(){ cout <<"Child class function\n"; }
};
int main(){
Child cObj;
cObj.f();
return 0;
}
输出:
Child class function
这里,请注意,子类对象调用子类的 f()
函数(而不是来自父类)。 要通过子类对象调用父类的 f()
,我们必须使用父类名称和作用域解析运算符 (::
),如以下代码所示。
class Parent{
public:
void f(){ cout << "Parent class function\n"; }
};
class Child: public Parent{
public:
void f(){ cout <<"Child class function\n"; }
};
int main(){
Child cObj;
cObj.Parent::f(); //calling f() of parent class
cObj.f();
return 0;
}
输出:
Parent class function
Child class function
请参阅 main() 函数中的第二行,其中我们使用了父类名称和范围解析运算符。 相应地,在输出的第一行,我们可以看到父类的f()打印的消息。
应遵循确切的语法来调用子类中的基类函数,如下面的代码所示。
class Parent{
public:
void f(){ cout << "Parent class function\n"; }
};
class Child: public Parent{
public:
void f(){
Parent::f();
cout <<"Child class function\n";
}
};
int main(){
Child cObj;
cObj.f();
return 0;
}
输出:
Parent class function
Child class function
多重继承歧义
调用基类方法的第二个问题是多个(两个或多个)类父类可以具有相同的方法。 在这种情况下,编译器会混淆选择特定的基类来调用该方法,因为相同的方法存在于多个基类中。
让我们看一下在选择特定基类来调用基方法时将为编译器生成编译时歧义的代码。
class P1{
public:
void fun(){ cout << "Fun from P1\n"; }
};
class P2{
public:
void fun(){ cout << "Fun from P2\n"; }
};
class C:public P1, public P2{};
int main(){
C objC;
objC.fun();
return 0;
}
这里,类 C 继承自两个基类(即 P1 和 P2),并且两个父类都有一个具有相同签名的 fun()
方法。
现在,当驱动程序代码通过子对象 (objC) 调用 fun()
函数时,编译器会在选择正确的基类时感到困惑。
让我们看看编译器消息。
base_class_3.cpp: In function ‘int main()’:
base_class_3.cpp:16:7: error: request for member ‘fun’ is ambiguous
objC.fun();
该消息清楚地表明编译器感到困惑。 同样,解决方案是相同的,即使用类名和范围解析运算符。
请参阅代码和相关输出。
class P1{
public:
void fun(){ cout << "Fun from P1\n"; }
};
class P2{
public:
void fun(){ cout << "Fun from P2\n"; }
};
class C:public P1, public P2{};
int main(){
C objC;
objC.P1::fun();
objC.P2::fun();
return 0;
}
输出:
Fun from P1
Fun from P2
请参阅 main()
中的第 2 行和第 3 行,其中 P1 和 P2 类名与范围解析运算符一起使用。 因此,在输出中,您可以看到两个基本函数的输出。
相关文章
Arduino 复位
发布时间:2024/03/13 浏览次数:315 分类:C++
-
可以通过使用复位按钮,Softwarereset 库和 Adafruit SleepyDog 库来复位 Arduino。
Arduino 的字符转换为整型
发布时间:2024/03/13 浏览次数:181 分类:C++
-
可以使用简单的方法 toInt()函数和 Serial.parseInt()函数将 char 转换为 int。
Arduino 串口打印多个变量
发布时间:2024/03/13 浏览次数:381 分类:C++
-
可以使用 Serial.print()和 Serial.println()函数在串口监视器上显示变量值。