虚函数调用的几种方式
虚函数调用的几种方式
/* * 虚函数的三种调用 * 1: 指针 * 2: 引用 * 3: 对象(不能实现多态) */ #include <iostream> //继承,默认情况下class是私有继承 struct默认是公有继承 //虚函数可以调用成员函数 //多态调用依赖于指针 或 引用调用 //对象的调用有副本机制,会调用拷贝构造 拷贝一个父类 无法实现多态 //p->go(); //多态调用 //p->myclass::go(); //原生调用 //虚函数重载和返回值无关 和参数的类型 个数 顺序有关 //虚函数被继承下来了还是虚函数 //如果要使用被继承的虚函数 不允许出现虚函数重载和覆盖 //多态可以跨类 爷爷辈的指针 可以存储孙子辈的地址 父辈拔针的地址 class myclass { public: int i; virtual void go() { i = 0; show(); } void show() { std::cout << "myclass->show()" << std::endl; } virtual ~myclass() { // 不加virtual 会造成内存泄漏 } }; class newmyclass: public myclass { public: void go() { std::cout << "newmyclass->go()" << std::endl; } void show() { std::cout << "newmyclass->show()" << std::endl; } void put() { std::cout << "newmyclass->put()" << std::endl; } }; // 1: 指针 void test1(myclass *p) { p->go(); } // 2: 引用 void test2(myclass &p) { p.go(); } // 3: 对象 void test3(myclass my) { my.go(); } int main() { myclass my; my.go(); // 正常调用父类的go函数 newmyclass newmy; newmy.go(); // 正常调用子类的go函数 myclass *pmy(nullptr); pmy->show(); // 空指针可以调用show操作 //pmy->go(); // 空指针无法调用go函数,因为myclass类,没有实例化为对象,go函数内部操作了对象的内部变量,此时该内部变量并没有构造出来 myclass *p = new newmyclass; p->go(); // 调用子类的go函数 p->myclass::go(); // 指定调用父类的go函数 std::cout << typeid(p).name() << std::endl; // p的类型为父类类型指针 class myclass * std::cout << typeid(*p).name() << std::endl; // *p的类型为子类类型 class newmyclass test1(p); // 调用子类的go函数 test1(&my); // 调用父类的go函数 test1(&newmy); // 调用子类的go函数 // 引用在语言内部用指针实现,引用是操作受限了的指针(仅容许取内容操作) test2(*p); // 调用子类的go函数 test2(my); // 调用父类的go函数 test2(newmy); // 调用子类的go函数 // 对象作为参数,会使用拷贝构造函数,形成对象的副本 test3(*p); // 调用父类的go函数 test3(my); // 调用父类的go函数 test3(newmy); // 调用父类的go函数 //std::cout << "mytest" << std::endl; system("pause"); return 0; }
运行结果: