C++中的多态

先来几个常见的面试题:
1、如何实现不能被继承的类?
需要的知识点
私有继承以后不可见,构造函数合成
解决方法:
这里写图片描述

   class AA
{
public:
    void func1()
    {}
    static AA* Getvariable1()//static 是为了没有对象也能调//无this指针就要加static
    {
        return new AA;//直接new出一个对象
    }
    static AA Getvariable2()
    {
        return AA();//利用拷贝构造
    }
private:
    AA()//拷贝构造
    {

    }
    int _a;//变量
};
class BB:public AA
{};
int main()
{
    AA*p1 = AA::Getvariable1();
    AA p2 = AA::Getvariable2();
    system("pause");
    return 0;
} 

2、如何实现一个类,定义出的对象都在堆上?
如何实现一个类,定义出的对象都在栈上?

思路:
这里写图片描述
代码:

class AA
{
public:
    void func1()
    {}
    static AA* Getvariable1()
    {
        return new AA;//直接new出一个对象(对象都在堆上)
    }
    //static AA Getvariable2()
    //{
    //  return AA();//利用拷贝构造
    //}
private:
    AA()//拷贝构造
    {

    }
    AA(const AA& a);//构造
    AA& operator=(const AA&a);//赋值运算符重载
    int _a;//变量
};
int main()
{
    AA* p1 = AA::Getvariable1();
    AA p2 = *p1;
    system("pause");
    return 0;
}


方法一:

class AA
{ 
public:
    void* operator new(size_t size);
    void operator delete(void* p);

private:



    int _a;//变量
};
AA a;//堆上
int main()
{
    AA  p1;
    AA * p2 = new AA;
    system("pause");
    return 0;
}

有缺陷,在代码块中创建的可能不在栈上
方法二:

同堆的方法


接下来进入知识点部分:
一、虚函数:
虚函数&多态
虚函数类的成员函数前面加virtual关键字,则这个成员函数称为虚函数
虚函数重写–当在子类的定义了一个与父类完全相同的虚函数时,则称子类的这个函数重写(也称覆盖)了父类的这个虚函数。
多态:(1、虚函数的重写。2、对象的指针或者引用)
总结:
1. 派生类重写基类的虚函数实现多态,要求函数名、参数列表、返回值完全相同。(协变除外)
协变:不构成重写,返回值类型不同,一个为父类返回值,一个为子类返回值。
2. 基类中定义了虚函数,在派生类中该函数始终保持虚函数的特性。
3. 只有类的成员函数才能定义为虚函数
4. 静态成员函数不能定义为虚函数。
5. 如果在类外定义虚函数,只能在声明函数时加virtual类外定义函数时不能加virtual。
6. 构造函数不能为虚函数,虽然可以将operator=定义为虚函数,但是最好不要将operator=定义为虚函数,因为容易使用时容易引 起混淆。
赋值运算符重载不会构成重写,因为返回值类型不同,最好不要定义为虚函数是因为它没有必要构成多态,没意义
7. 不要在构造函数和析构函数里面调用虚函数,在构造函数和析构函数中,对象是不完整的,可能会发生未定义的行为。
这里写图片描述
8. 最好把基类的析构函数声明为虚函数。(why?另外析构函数比较特殊,因为派生类的析构函数跟基类的析构函数名称不一样,但 是构成覆盖,这里是因为编译器做了特殊处理)
编译器将父类与子类的析构函数都处理为destructor,加上virtual后构成重写
面试题:
什么情况下把基类的析构函数定义为虚函数?
1)free delete
2)fclose
这里写图片描述
二、重载、重写、重定义、协变的区别
重载:在同一个作用域,函数名形同,参数类型或参数个数不同
重写(覆盖):在两个作用域,即基类和子类,函数名形同,返回值相同,参数个数和类型相同
协变:与重写基本相同,除了返回值类型不同
重定义(隐藏):与重写相似,不构成重写,就是重定义
三、纯虚函数: 纯虚函数让子类必须重写虚函数

在成员函数的形参后面写上=0,则成员函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。纯虚 函数在派生类中重新定义以后,派生类才能实例化出对象。

//抽象类、接口类

class Person
 {     
   virtual void Display () = 0;   // 纯虚函数 protected :     string _name ;  // 姓名 
 };
class Student : public Person {};

四、友元与继承
友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。
五、继承与静态成员
基类定义了static成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static成员实例。
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值