关于多重继承指针回退传递的细节。
2013-09-27 14:18
211 查看
引言: 在一个产品中, 看到把一个实现类指针 this, 同时传递给接口Tx, Rx 有感。
当时这个接口没有写好,子类和父类在函数原型定义上一个是const, 一个未定为const, 使得基类传递不给继承类。
这种差别,已经不能称为父子关系了。
接口工作不了,才不得不多看了一眼。并认真的思考了一下问题。
--------------------------------------------------------------------------------
关于多重继承指针回退传递的细节。
1. 问题提出
c 语言时代,有回调函数。 是说传递来一个函数指针,我们来调用这个函数。
这样我们并不关心这个函数的实现,而只是关心这个函数的接口。即它的参数类型,参数个数。
c++时代,进一步表现为。传递过来一个对象指针。我们来调用这个对象的成员函数。
这就是类的回调函数。对于正在写底层逻辑的你来说, 你不关心这个回调对象的实现,而只是
关心它的接口。
c时代,传来的函数可以有不同的地址,从而有不同的表现。
c++时代,这个传来的指针可以是不同的对象。因而也可以有不同的表现形式。但实现这种变化必须要求
各对象具有相同的基类。基类中要求变化的函数声明为虚函数,并且当函数需要不同的表现时,继承类重载基类对应的函数。
看起来,c++一下子比c复杂了不少。
c++实现这种要求的方法是通过建立虚函数表来完成的。
在还不知道未来继承类是怎样实现的情况下, 基础的逻辑控制函数就已经按照基类的要求来完成它的处理流程了。
这里碰到了一种情况。 一个实现类继承了两个虚基类Rx, Tx.
在书写函数时,已经写好了控制流程。 并且这个实现类 implemnet RXTX 也已经完成。
问题是,这个实现类对象,怎样传递给虚基类指针Rx, Tx.
我们知道,子类会退化为父类指针,对应单继承很好理解,对应多重继承, 难道说这个子类即能退化为Tx, 又能退化为Rx吗?
带着这种疑惑, 我研究了这个问题的汇编代码。 得出了结论:
子类在退化为父类指针时,并不是简单的指针赋值,而有可能调整指针位置,这就是c++编译器的强大复杂之处。
2. 研究这个问题的例子。(源码)
#include "stdafx.h"
#include <conio.h>
#include <locale.h>
#include "windows.h"
class Tx
{
public:
virtual void tx_exec() {
printf("Tx not implement!\n");
}
private:
char a;
char b;
};
class Rx
{
public:
virtual void rx_exec() {
printf("Rx not implement!\n");
}
private:
int i;
int j;
};
class RxTx: public Tx, public Rx
{
public:
void tx_exec() {printf("Tx has implement!\n");}
void rx_exec() {printf("Rx has implement!\n");}
};
void test(Tx *pTx, Rx *pRx)
{
pTx->tx_exec();
pRx->rx_exec();
}
int main(int argc, char* argv[])
{
RxTx obj;
test(&obj, &obj); // 奥妙就在这里, 前一个&obj, 与后一个&obj 是不同的地址被压栈。
// 因为obj 包含两个类,前一个地址&obj 指向 Tx 对象部分, 后一个地址&obj 指向 Rx对象部分。
// Tx对象部分,Rx对象部分第一个参数分别对应各自的虚函数表。从而实现完美退化。
_getch();
return 0;
}
阅读此文,希望你对程序架构一词有更深的理解。 架构就是架子。就是在还没有实现类的时候,就已经用基础类在运转了。
体现"实现"与"接口"的分离。 实际上就是基类和继承类分离。 就是c++ 继承概念。不同的对象表现,就是多态概念。阿弥陀佛!...
补充: 如果一个实现类需要很多的接口时, 可以采用SendMessage 的结构。 把消息用命令类型来分类。 这样就可以省略很多接口指针。
MFC 的sendmessage, postmaessage 就是很好的例子。
当时这个接口没有写好,子类和父类在函数原型定义上一个是const, 一个未定为const, 使得基类传递不给继承类。
这种差别,已经不能称为父子关系了。
接口工作不了,才不得不多看了一眼。并认真的思考了一下问题。
--------------------------------------------------------------------------------
关于多重继承指针回退传递的细节。
1. 问题提出
c 语言时代,有回调函数。 是说传递来一个函数指针,我们来调用这个函数。
这样我们并不关心这个函数的实现,而只是关心这个函数的接口。即它的参数类型,参数个数。
c++时代,进一步表现为。传递过来一个对象指针。我们来调用这个对象的成员函数。
这就是类的回调函数。对于正在写底层逻辑的你来说, 你不关心这个回调对象的实现,而只是
关心它的接口。
c时代,传来的函数可以有不同的地址,从而有不同的表现。
c++时代,这个传来的指针可以是不同的对象。因而也可以有不同的表现形式。但实现这种变化必须要求
各对象具有相同的基类。基类中要求变化的函数声明为虚函数,并且当函数需要不同的表现时,继承类重载基类对应的函数。
看起来,c++一下子比c复杂了不少。
c++实现这种要求的方法是通过建立虚函数表来完成的。
在还不知道未来继承类是怎样实现的情况下, 基础的逻辑控制函数就已经按照基类的要求来完成它的处理流程了。
这里碰到了一种情况。 一个实现类继承了两个虚基类Rx, Tx.
在书写函数时,已经写好了控制流程。 并且这个实现类 implemnet RXTX 也已经完成。
问题是,这个实现类对象,怎样传递给虚基类指针Rx, Tx.
我们知道,子类会退化为父类指针,对应单继承很好理解,对应多重继承, 难道说这个子类即能退化为Tx, 又能退化为Rx吗?
带着这种疑惑, 我研究了这个问题的汇编代码。 得出了结论:
子类在退化为父类指针时,并不是简单的指针赋值,而有可能调整指针位置,这就是c++编译器的强大复杂之处。
2. 研究这个问题的例子。(源码)
#include "stdafx.h"
#include <conio.h>
#include <locale.h>
#include "windows.h"
class Tx
{
public:
virtual void tx_exec() {
printf("Tx not implement!\n");
}
private:
char a;
char b;
};
class Rx
{
public:
virtual void rx_exec() {
printf("Rx not implement!\n");
}
private:
int i;
int j;
};
class RxTx: public Tx, public Rx
{
public:
void tx_exec() {printf("Tx has implement!\n");}
void rx_exec() {printf("Rx has implement!\n");}
};
void test(Tx *pTx, Rx *pRx)
{
pTx->tx_exec();
pRx->rx_exec();
}
int main(int argc, char* argv[])
{
RxTx obj;
test(&obj, &obj); // 奥妙就在这里, 前一个&obj, 与后一个&obj 是不同的地址被压栈。
// 因为obj 包含两个类,前一个地址&obj 指向 Tx 对象部分, 后一个地址&obj 指向 Rx对象部分。
// Tx对象部分,Rx对象部分第一个参数分别对应各自的虚函数表。从而实现完美退化。
_getch();
return 0;
}
阅读此文,希望你对程序架构一词有更深的理解。 架构就是架子。就是在还没有实现类的时候,就已经用基础类在运转了。
体现"实现"与"接口"的分离。 实际上就是基类和继承类分离。 就是c++ 继承概念。不同的对象表现,就是多态概念。阿弥陀佛!...
补充: 如果一个实现类需要很多的接口时, 可以采用SendMessage 的结构。 把消息用命令类型来分类。 这样就可以省略很多接口指针。
MFC 的sendmessage, postmaessage 就是很好的例子。
相关文章推荐
- 关于数组指针,字符串指针的一些小细节
- 关于 指针的引用和指针值传递
- C++多重继承下的指针类型转换
- 关于二维数组与二维指针传递参数
- 关于Scala多重继承的菱形问题
- MFC关于多线程中传递窗口类指针时ASSERT_VALID出错的另类解决 转
- [C++]关于指针作为函数参数传递
- Java中关于多重继承的问题
- C++多重继承子类和父类指针转换过程中的一个易错点
- 关于值传递和指针传递
- 关于函数的指针传递
- 关于类继承中子类方法比父类方法丰富,一个引用值传递的小问题
- C语言——关于指针传递指针
- 关于指针参数的内存传递副本
- 关于多重继承的陷阱
- c++多重继承下虚函数的this指针问题
- 多重继承与void*指针转换问题的分析
- C++多重继承下的指针类型转换 图解
- 关于多重继承和虚拟继承
- C++继承中基类和派生类之间指针传递问题