c++ 父类指针转换为子类指针后调用子类的成员函数问题
2014-04-12 10:39
603 查看
#include <iostream> using namespacestd ; class A{ public: void display(){cout << "A class" << endl ;} } ; class B:public A{ public: void displayB(){cout << "B class" << endl ;} } ; int main(){ A a ; ((B*)&a)->displayB() ; return 0 ; }
屏幕输出B class 照理说,只是进行了指针的转换,内存中并不是真实存在B类对象的,为什么只是转换了指针类型之后就可以调用成功呢?
对比分析下面一段代码:
int main() { int a ; // 是int哦 ((B*)&a)->displayB() ; return 0 ; }
试试这个代码就可以知道了. 同样可以执行成功.只是因为你的B::displayB函数太简单了, 没有使用任何的类成员.若是class B里面定义一个 成员x, 然后displayB输出这个x, 那么强制转换之后才会出现错误.下面做下总结:
1,直接用基类指针引用基类对象 2,直接用派生类指针引用派生类对象 3,用基类指针引用一个派生类对象,由于派生类对象也是基类的对象,所以这种引用是安全的, 但是只能引用基类成员。若试图通过基类指针引用那些只在派生类中才有的成员,编译器会报告语法错误。(解决该问题的答案是虚函数和多态性) 4,用派生类指针引用基类的对象。这种引用方式会导致语法错误。派生类指针必须先强制转换为基类指针,这种方法是不安全的。 而在侯捷的深入浅出MFC中第二章C++重要性质中: 1、如果你以一个"基类之指针"指向一个"派生类之对象",那么经由该指针你只能调用该基类所定义的函数 2、如果你以一个“派生类之指针”指向一个“基类之对象”,你必须先做明显的转型操作(explicit cast),这种作法很危险。 3、如果基类和派生类都定义了“相同名称之函数”,那么通过对象指针调用成员函数时,到底调用了那个函数,必须视该指针的原始类型而定,而不是视指针实际所指的对象的类型而定,这与第1点其实意义相通。 #include <iostream> #include <stdlib.h> using namespace std; class A { public: char str[20]; void f(){cout<<"class A"<<endl;} void fff(){cout<<"class A's str "<<str<<endl;} void add(){cout<<"class A address: "<<this<<endl;} }; class B:public A { public: int i; char sb[20]; B(){cout<<"class B constructor is run."<<endl;} ~B(){cout<<"class B destructor is run."<<endl;} void f(){cout<<"class B"<<endl;} void ff(){cout<<"class B "<<i<<str<<sb<<endl;} void add(){cout<<"class B address: "<<this<<endl;} }; int main(int argc, char *argv[]) { //声明父类对象 A b; //声明父类对象的指针,指向父类对象 A *pa=&b; pa->add(); //这个写法正确,不过很危险,因为pa到底是指向B还是A是不确定的.如果能明确的知道 //pa是指向B类对象的,就如现在写的这个,那么没问题,如果pa指向A类对象,就会存在 //风险.改变指针的类型,并不会影响内存分配既不会调用构造函数 B *pb=(B *)pa; //类型强制转化后,指向的地址相同. 但会按转化类型访问数据成员. //成员函数属于类而不属于对象.各对象共用类的成员函数.强制转换成 B 类型后,可 //调用类的成员函数。编译pb->add();后的代码只是调用add函数的时候传入了pb的对 //象指针this pb->add(); //由于pa指向的是父类对象的地址,这个指针被强制转换为派生类指针后,会出现内存越 //界访问的情况,是不安全的. pb->i=100; char dsd[100]; strcpy(pb->sb, " class B's sb."); strcpy(pb->str, " class A's str."); //pb->f()调用的具体函数,视指针的原始类型而定,而不是视指针实际所指的对象的 //类型而定.如果是虚函数,则视实际所指的对象的类型而定 pb->f(); pb->ff(); pb->fff(); system("PAUSE"); return 0; }
相关文章推荐
- Gvim自动编译运行c++11的程序
- C++中的std详解
- 忙里偷闲( ˇˍˇ )闲里偷学【C语言篇】——(4)for == while ?
- 忙里偷闲( ˇˍˇ )闲里偷学【C语言篇】——(4)for == while ?
- C++ Primer笔记(二)标准库类型
- C++ Primer笔记(一)变量和基本类型
- c语言的函数内存分配及指针函数的用法
- Effective C++——》条款25:考虑写一个不抛出异常的swap函数
- 【面试题004】c/c++字符串,替换空格
- 关于前置声明与C++中头文件相互包含的几点问题
- 忙里偷闲( ˇˍˇ )闲里偷学【C语言篇】——(3)输入输出函数
- 忙里偷闲( ˇˍˇ )闲里偷学【C语言篇】——(3)输入输出函数
- C语言进阶(牟海军)C 语言指针理解 续(2)
- Effective C++——》条款24:若所有参数皆需类型转化,请谓词函数采用non-member函数
- C语言中sscanf的用法
- Effective C++——》条款23:宁以non-member、non-frined替换member函数
- 钥匙计数之二
- C++随记:【cstdio(25) : error C2143: syntax error : missing '{' before ':'】
- C/C++语言void及void指针深层探索
- C++泛型算法