多态公有继承(虚函数)

基类
class class_A
{
 private:
    enum{MAX=35};
    char fullName[MAX];
    long acctNum;
    double balance;
 public:
    class_A(const char* s="Nullbody",long an= -1,double bal= 0.0);
    void Deposit(double amt);
    virtual void Withdraw(double amt);
    double Balance()const;
    virtual void ViewAcct()const;
    virtual ~class_A(){}
};

 

公有派生类
class class_B: public class_A
{
 private:
    double maxLoan,rate,owesBank;
 public:
    class_B(const char* s="Nullbody",long an= -1,double bn= 0.0,
            double ml= 500,double r=0.10);
    class_B(const class_A & ba,double ml= 500,double r=0.10);
    virtual void ViewAcct()const;
    virtual void Withdraw(double d);
    void ResetMax(double m){maxLoan=m;}
    void ResetRate(double r){rate=r;}
    void ResetOwes(){owesBank=0;}
}

 

使用虚方法(虚函数)
    关键字virtual,定义虚方法.只用于函数原型,不能用于函数定义中。
    class_A类在声明ViewAcct()和Withdraw()时使用了关键字virtual。这些方法被称为虚方法(virtual method).
    在基类中被声明为虚拟的后,他在派生类中将自动成为虚方法。不过,在派生类声明中使用关键字virtual来明确指出哪些函数是虚函数也不失为一个好办法。

 

基类版本的限定名为class_A::ViewAcct()。
派生类版本的限定名为class_B::ViewAcct()。

 

程序将使用对象类型来确定使用哪个版本:
class_A A("TypeCool",11224,4183.45);
class_B B("DorothyBanker",12118,2592.00);
A.ViewAcct();
  //use class_A::ViewAcct()
B.ViewAcct();  //use class_B::ViewAcct()

 

当方法是通过引用或指针而不是对象调用时

 

对于没有使用关键字virtual,程序将根据引用类型或指针类型选择方法:
(等于是在派生类中直接重新定义基类的方法)
//behavior with non-virtual ViewAcct()
//method chosen according to reference type

class_A A("TypeCool",11224,4183.45);
class_B B("DorothyBanker",12118,2592.00);
class_A & A1=A;
class_A & A2=B;
A1.ViewAcct();
  //use class_A::ViewAcct()
A2.ViewAcct();  //use class_A::ViewAcct()

 

如果使用了virtual,程序将根据引用或指针指向的对象的类型来选择方法:
//behavior with virtual ViewAcct()
//method chosen according to object type

class_A A("TypeCool",11224,4183.45);
class_B B("DorothyBanker",12118,2592.00);
class_A & A1=A;
class_A & A2=B;
A1.ViewAcct();
  //use class_A::ViewAcct()
A2.ViewAcct();  //use class_B::ViewAcct()

 

在派生类方法中,标准的技术是使用作用域解析操作符来调用基类方法:
void class_B::ViewAcct()const { class_A::ViewAcct(); }

 

    由于使用的是公有继承模型,因此基类指针既可以指向基类对象,也可以指向派生类对象。那么可以使用一个基类指针数组来表示多种类型的对象。这就是多态性。关于派生类和基类之间的特殊关系的更多介绍请查看<<公有派生(公有继承) 及 该派生类和基类之间的特殊关系 >>

 

虚拟析构函数
    作为基类,应该包含一个虚拟析构函数。对于用基类指针数组来表示的多种类型对象来说,如果基类析构函数不是虚拟的,则将只调用对应指针类型的析构函数。这意味着只有基类的析构函数被调用,即使指针指向的是一个派生类对象。如果基类析构函数是虚拟的,将调用相应对象类型的析构函数。假如指针指向的是派生类对象,将调用派生类对象的析构函数,然后自动调用基类的析构函数。因此,使用基类虚拟析构函数可以确保正确的析构函数序列被调用,即使该析构函数不执行任何操作。

 

构造函数不能是虚函数
创建派生类对象时,将调用派生类的构造函数,而不是基类的。然后,派生类的构造函数将使用基类的一个构造函数,这种顺序不同于继承机制。因此,派生类不继承基类的构造函数,所以类构造函数声明为虚拟的是没有意义的。


友元不能是虚函数

因为友元不是类成员,而只有成员才能是虚函数。

 

重新定义隐藏方法

class class_a
{public:
    virtual void show(int a)const;
 ...
};
class class_b:public class_a
{public:
    virtual void show()const;
 ...
};

 

代码将具有如下含义:
class_b x;
x.show();      //valid
x.show(10);  //invalid

 

重新定义继承的方法并不是重载。
如果在派生类中重新定义函数,将不是使用相同的函数特征标覆盖基类声明,而是
隐藏同名的基类方法,不管参数特征标如何。

 

虚函数经验规则

1.如果重新定义继承的方法,应确保与原来的原型完全相同,但如果返回类型是基类引用或指针,则可以修改为指向派生类的引用或指针。这种特性被称为返回类型协变(covariance of return type),因为允许返回类型随类类型的变化而变化。
这种例外只适用于返回值,而不适用于参数。

class class_a
{public:
    //a base method
    virtual class_a & show(int a)const;
 ...
};
class class_b:public class_a
{public:
    //a derived method with a covariant return type
    virtual class_b & show(int a)const;
 ...
};

2.如果基类声明被重载了,则应在派生类重新定义所有的基类版本。

class class_a
{public:
    //three overloaded show()
    virtual void show(int a)const;
    virtual void show(double x)const;
    virtual void show()const;
 ...
};
class class_b:public class_a
{public:
    //three redefined show()
    virtual void show(int a)const;
    virtual void show(double x)const;
    virtual void show()const;
 ...
};

 

如果只重新定义一个版本,则剩下的版本将被隐藏,派生类对象将无法使用它们。注意,如果不需要修改,则新定义可只调用基类版本。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++中的继承多态虚函数是面向对象编程的重要概念。 继承是指一个类可以从另一个类继承属性和方法。子类可以继承父类的公有成员和保护成员,但不能继承私有成员。通过继承,子类可以重用父类的代码,并且可以添加自己的特定功能。继承可以实现代码的重用和层次化的设计。 多态是指同一个函数可以根据不同的对象调用不同的实现。多态可以通过虚函数来实现。虚函数是在基类中声明为虚拟的函数,它可以在派生类中被重写。当通过基类指针或引用调用虚函数时,实际调用的是派生类中的实现。这样可以实现动态绑定,即在运行时确定调用的函数。 虚函数的原理是通过虚函数表来实现的。每个包含虚函数的类都有一个虚函数表,其中存储了虚函数的地址。当调用虚函数时,编译器会根据对象的类型在虚函数表中查找对应的函数地址并调用。 综上所述,C++中的继承多态虚函数是实现面向对象编程的重要机制,它们可以提高代码的灵活性和可扩展性。 #### 引用[.reference_title] - *1* *3* [C++多态虚函数虚函数表](https://blog.csdn.net/weixin_46053588/article/details/121231465)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [c++多态虚函数表内部原理实战详解](https://blog.csdn.net/bitcarmanlee/article/details/124830241)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值