OOP 一些例题

例题一

#include <iostream>
using namespace std;

class Animal
{
    
    
public:
    Animal(string name) :name_(name) {
    
    }

    virtual void bark() = 0;
protected:
    string getName() {
    
     return name_; }
private:
    string name_;
};

class Cat : public Animal {
    
    
public:
    Cat(string name) : Animal(name){
    
    }
    void bark() {
    
    
        cout << "Cat " << getName() << "miao miao miao" << endl;
    }
};
class Dog : public Animal {
    
    
public:
    Dog(string name) : Animal(name) {
    
    }
    void bark() {
    
    
        cout << "Dog " << getName() << "wang wang wang" << endl;
    }
};
int main()
{
    
    
    Animal* cat = new Cat("罗小黑");
    Animal* dog = new Dog("布鲁托");
    
    int* p = (int*)cat;
    int* q = (int*)dog;
    int tmp = p[0];
    p[0] = q[0];
    q[0] = tmp;
    cat->bark();
    dog->bark();
}

运行结果: Dog 罗小黑wang wang wang
Cat 布鲁托miao miao miao

原因:将Cat与Dog的虚表指针vfptr交换了,导致调用的函数互换了

例题二

class Base {
    
    
public:
    virtual void show(int i = 10)
    {
    
    
        cout << "Base::show() " << i << endl;
    }
};

class Drived : public Base
{
    
    
public:
    virtual void show(int i = 20)
    {
    
    
        cout << "Drived::show() " << i << endl;
    }
};
int main()
{
    
    
    Base* b = new Drived;
    b->show();
}

运行结果 Drived::show() 10

原因:编译阶段,会将基类的show()函数,如果该函数有默认形参那么将其形参默认值入栈。但是运行时期,是调用的虚函数表的函数地址。

具体汇编代码如下,

b->show();
00007FF66DED2692  mov         rax,qword ptr [b]  
00007FF66DED2696  mov         rax,qword ptr [rax]  
00007FF66DED2699  mov         edx,0Ah   // 基类的show()默认形参10
00007FF66DED269E  mov         rcx,qword ptr [b]  
00007FF66DED26A2  call        qword ptr [rax]

例题三


class Base {
    
    
public:
    virtual void show()
    {
    
    
        cout << "Base::show() " << endl;
    }
};

class Drived : public Base
{
    
    
private:
    virtual void show()
    {
    
    
        cout << "Drived::show() " << endl;
    }
};
int main()
{
    
    
    Base* b = new Drived;
    b->show();
    delete b;
}

运行结果Drived::show()

原因编译阶段,编译器首先是否拥有函数访问权限。代码中,使用的是基类指针,所以编译器检查的是基类中show()的权限。而具体调用的show()是在运行阶段,因为基类使用虚函数,所以调用show()的时候动态绑定。尽管派生类的show()函数是私有的,但是其地址是在虚函数表中,因此从虚表中调用派生类的show()函数。

例题四

class Base {
    
    
public:
    Base()
    {
    
    
        cout << "Base Construct" << endl;
        clear();
    }

    void clear(){
    
    
        memset(this, 0, sizeof(*this));
    }
    virtual void show()
    {
    
    
        cout << "Base::show() " << endl;
    }
};

class Drived : public Base
{
    
    

public:
    Drived() {
    
    
        cout << "Drived Construct" << endl;
    }
    virtual void show()
    {
    
    
        cout << "Drived::show() " << endl;
    }
};
int main()
{
    
    

    /*Base* b1 = new Base(); // 运行错误
    b1->show();*/

    Base* b2 = new Drived;   // 运行失败
    b2->show();
}

猜你喜欢

转载自blog.csdn.net/weixin_43459437/article/details/143366327
OOP