你真的懂 C++ 多态吗?我不信

好,不要看答案,请你写出以下程序完整的输出(包括哪些语法有问题):

#include <iostream>

class Base {
public:
    Base() {
        std::cout << "Base::construct\n";
    }
    virtual ~Base() {
        std::cout << "Base::destruct\n";
    }
    virtual void foo() {
        std::cout << "Base::foo()\n";
    }
    void fun() {
        std::cout << "Base::fun()\n";
    }
    void bar() {
        std::cout << "Base::bar()\n";
    }
};

class Derive : public Base {
public:
    Derive() {
        std::cout << "Derive::construct\n";
    }
    ~Derive() {
        std::cout << "Derive::destruct\n";
    }
    void foo() override {
        std::cout << "Derive::foo()\n";
    }
    void fun() {
        std::cout << "Derive::fun()\n";
    }
    virtual void bar() {
        std::cout << "Derive::bar()\n";
    }
};

void fun1(Base *base) {
    std::cout << "void fun1(Base * base)\n";
}

void fun2(Derive *derive) {
    std::cout << "void fun2(Derive * derive)\n";
}


int main() {

    // 测试一:基类指针指向基类成员
    {
        Base b1;
        Base *b2 = &b1;
        b1.foo();
        b1.fun();
        b1.bar();
        b2->foo();
        b2->fun();
        b2->bar();

        fun1(&b1);
        fun1(b2);

        fun2(&b1);
        fun2(b2);

    }

    std::cout << "\n\n----------------------------\n\n";

    // 测试二:基类指针指向子类成员
    {
        Derive d;
        Base *b = &d;

        d.foo();
        d.fun();
        d.bar();
        b->foo();
        b->fun();
        b->bar();

        fun1(&d);
        fun1(b);

        fun2(&d);
        fun2(b);
    }

    std::cout << "\n\n----------------------------\n\n";

    // 测试三:子类指针指向基类成员
    {
        Base b;
        Derive *d = &b;

        b.foo();
        b.fun();
        b.bar();
        d->foo();
        d->fun();
        d->bar();

        fun1(&b);
        fun1(d);

        fun2(&b);
        fun2(d);
    }

    std::cout << "\n\n----------------------------\n\n";

    // 测试四:子类指针指向子类
    {
        Derive d1;
        Derive *d2 = &d1;

        d1.foo();
        d1.fun();
        d1.bar();
        d2->foo();
        d2->fun();
        d2->bar();

        fun1(&d1);
        fun1(d2);

        fun2(&d1);
        fun2(d2);

    }

    return 0;
}

如果你不是信手拈来,那这篇博客对你有价值,请先看答案,给自己打打分数:

Base::construct
Base::foo()
Base::fun()
Base::bar()
Base::foo()
Base::fun()
Base::bar()
void fun1(Base * base)
void fun1(Base * base)
void fun2(Derive * derive)
void fun2(Derive * derive)
Base::destruct


----------------------------

Base::construct
Derive::construct
Derive::foo()
Derive::fun()
Derive::bar()
Derive::foo()
Base::fun()
Base::bar()
void fun1(Base * base)
void fun1(Base * base)
void fun2(Derive * derive)
void fun2(Derive * derive)
Derive::destruct
Base::destruct


----------------------------

Base::construct
Base::foo()
Base::fun()
Base::bar()
Base::foo()
Derive::fun()
void fun1(Base * base)
void fun1(Base * base)
void fun2(Derive * derive)
void fun2(Derive * derive)
Base::destruct


----------------------------

Base::construct
Derive::construct
Derive::foo()
Derive::fun()
Derive::bar()
Derive::foo()
Derive::fun()
Derive::bar()
void fun1(Base * base)
void fun1(Base * base)
void fun2(Derive * derive)
void fun2(Derive * derive)
Derive::destruct
Base::destruct

怎么样,是不是感觉到自己还存在一些问题,请看具体代码注释:

#include <iostream>

// 基类
class Base {
public:
    Base() {
        std::cout << "Base::construct\n";
    }
    // 虚析构
    virtual ~Base() {
        std::cout << "Base::destruct\n";
    }
    // virtual,产生多态的关键字
    virtual void foo() {
        std::cout << "Base::foo()\n";
    }
    // 普通成员函数
    void fun() {
        std::cout << "Base::fun()\n";
    }
    // 普通成员函数
    void bar() {
        std::cout << "Base::bar()\n";
    }
};

// 子类
class Derive : public Base {
public:
    Derive() {
        std::cout << "Derive::construct\n";
    }
    ~Derive() {
        std::cout << "Derive::destruct\n";
    }
    // 重写,override
    void foo() override {
        std::cout << "Derive::foo()\n";
    }
    // 普通成员函数
    void fun() {
        std::cout << "Derive::fun()\n";
    }
    // 加上关键字 virtual 的普通成员函数
    virtual void bar() {
        std::cout << "Derive::bar()\n";
    }
};

// 基类指针作参数
void fun1(Base *base) {
    std::cout << "void fun1(Base * base)\n";
}

// 子类指针作参数
void fun2(Derive *derive) {
    std::cout << "void fun2(Derive * derive)\n";
}

int main() {

    // 测试一:基类指针指向基类成员
    {
        Base b1;            // 新建基类对象,调用构造函数,输出 Base::construct
        Base *b2 = &b1;     // 指向基类对象的基类指针,无输出!
        b1.foo();           // 毋庸置疑,调用父类自身的 Base::foo()
        b1.fun();           // 毋庸置疑,调用父类自身的 Base::fun()
        b1.bar();           // 毋庸置疑,调用父类自身的 Base::bar()
        b2->foo();          // 同理,调用父类自身的 Base::foo()
        b2->fun();          // 同理,调用父类自身的 Base::fun()
        b2->bar();          // 同理,调用父类自身的 Base::bar()

        fun1(&b1);          // 输出 void fun1(Base * base)
        fun1(b2);           // 输出 void fun1(Base * base)

        //fun2(&b1);                        // 转换失败,语法错误
        fun2(static_cast<Derive *>(&b1));   // 应该用 static_cast<Derive *>,输出 void fun2(Derive * derive)
        //fun2(b2);                         // 转换失败
        fun2(static_cast<Derive *>(b2));    // 同理,输出 void fun2(Derive * derive)

    }                                       // 到达作用域尾,析构,输出 Base::destruct

    std::cout << "\n\n----------------------------\n\n";

    // 测试二:基类指针指向子类成员
    {
        Derive d;           // 新建子类对象,先调用基类的构造函数 Base::construct,再调用自身的构造函数 Derive::construct
        Base *b = &d;       // 指向子类对象的基类指针,无输出!

        d.foo();            // 毋庸置疑,Derive::foo()
        d.fun();            // Derive::fun()
        d.bar();            // Derive::bar()
        b->foo();           // 构成多态,输出 Derive::foo()
        b->fun();           // 不是多态,Base::fun()
        b->bar();           // 不是多态,Base::bar(),说明 virtual 修饰子类的成员函数时不影响父类指针的执行

        fun1(&d);           // 子类地址复制给父类指针,输出 void fun1(Base * base)
        fun1(b);            // void fun1(Base * base)

        fun2(&d);           // void fun2(Derive * derive)
        //fun2(b);          // 转换失败
        fun2(static_cast<Derive *>(b));  // void fun2(Derive * derive)
    }                       // 离开作用域,先析构子类 Derive::destruct,再析构父类 Base::destruct

    std::cout << "\n\n----------------------------\n\n";

    // 测试三:子类指针指向基类成员
    {
        Base b;                      // 新建父类对象,输出 Base::construct,
        //Derive * d = &b;           // 语法错误,也就是说父类对象的地址不能赋值给子类指针
        Derive *d = (Derive *)&b;    // 正确姿势

        b.foo();                     // Base::foo()
        b.fun();                     // Base::fun()
        b.bar();                     // Base::bar()
        d->foo();                    // 子类指针指向父类,无法构成多态,依旧调用父类的方法,Base::foo()
        d->fun();                    // 普通成员函数,Derive::fun()
        //d->bar();                  // 行为未定义,想想为什么???

        fun1(&b);                    // void fun1(Base * base)
        fun1(d);                     // void fun1(Base * base)

        //fun2(&b);                  // 转换失败
        fun2(static_cast<Derive *>(&b)); // void fun2(Derive * derive)
        fun2(d);                         // void fun2(Derive * derive)
    }                                    // Base::destruct

    std::cout << "\n\n----------------------------\n\n";

    // 测试四:子类指针指向子类
    {
        Derive d1;            // Base::construct Derive::construct
        Derive *d2 = &d1;     // 无输出

        d1.foo();             //Derive::foo()
        d1.fun();             // Derive::fun()
        d1.bar();             // Derive::bar()
        d2->foo();            // Derive::foo()
        d2->fun();            // Derive::fun()
        d2->bar();            // Derive::bar()

        fun1(&d1);            // void fun1(Base * base)
        fun1(d2);             // void fun1(Base * base)

        fun2(&d1);            // void fun2(Derive * derive)
        fun2(d2);             // void fun2(Derive * derive)

    }                         // Derive::destruct Base::destruct

    return 0;
}

学海无涯 …

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值