C++允许我们定义一个基类的指针指向子类的数据空间(为了实现多态,所以需要这么操作):
BaseClass *c = new SubClass;
但当子类中存在覆盖基类的方法时,我们想用指针调用子类的方法,就会出现问题,结果是调用了基类的方法,比如下面的代码:
/*
**虚方法
*/
#include <iostream>
using namespace std;
class BaseClass
{
public:
void test();
};
class SubClass : public BaseClass
{
public:
void test();
};
void SubClass::test()
{
cout << "subClass test" << endl;
}
void BaseClass::test()
{
cout << "BaseClass test" << endl;
}
int main()
{
BaseClass *c = new SubClass;
c->test();
SubClass b;
b.test();
delete c;
return 0;
}
其运行结果如下:
BaseClass test
subClass test
第一行结果为指针调用test方法运行得到的结果,是基类的方法中的打印。第二行结果为定义的子类的对象调用test方法的结果,是子类覆盖的方法。
那么这样的原因是什么?
在编译的时候,编译器会为认为这里是一个BaseClass型的指针,因此也就认为指针中的test方法是基类的方法。
虚方法
虚方法的作用就是让编译器知道它应该根据这两个指针在运行时的类型而有选择地调用正确的方法。因为在实际运行中,我们分配的是subClass类型的指针。
定义一个虚方法就是在基类中对应的方法声明前加上virtual:
class BaseClass
{
public:
virtual void test();
};
修改后的代码
/*
**虚方法
*/
#include <iostream>
using namespace std;
class BaseClass
{
public:
virtual void test();
};
class SubClass : public BaseClass
{
public:
void test();
};
void SubClass::test()
{
cout << "subClass test" << endl;
}
void BaseClass::test()
{
cout << "BaseClass test" << endl;
}
int main()
{
BaseClass *c = new SubClass;
c->test();
SubClass b;
b.test();
delete c;
return 0;
}
实际运行结果:
subClass test
subClass test
可以看到指针运行的test方法现在是子类的方法了。
另外一点
定义一个基类的指针指向子类的数据空间,但这个指针不能直接使用子类中基类没有的方法和属性。比如下面的代码编译时候会报错:
#include <iostream>
using namespace std;
class BaseClass
{
public:
virtual void test();
};
class SubClass : public BaseClass
{
public:
void privTest();
void test();
};
void SubClass::test()
{
cout << "subClass test" << endl;
}
void SubClass::privTest()
{
cout << "privTest" <<endl;
}
void BaseClass::test()
{
cout << "BaseClass test" << endl;
}
int main()
{
BaseClass *c = new SubClass;
c->test();
c->privTest(); //此处编译器报错
return 0;
}
报错内容:
[Error] 'class BaseClass' has no member named 'privTest'