C++ 多继承 父类是虚基类和非虚基类时 父类指针值问题

C++语言 码拜 7年前 (2017-04-26) 1745次浏览
大家好!本人遇到一个问题,本人很疑惑,希望能得到大家的帮助,并帮本人指出是哪个知识点欠缺了,非常感谢。
问题概述:
多继承时,当基类有没有虚函数,有没有成员变量时,基类的this指针和子类会出现不同。例子如下:
代码如下:

#include <time.h> 
#include <stdio.h>
#include <stdarg.h>
#if defined(WINDOWS)
#include <Windows.h>
#include <process.h>
#else
#include <sys/time.h>
#include <pthread.h>
#include <unistd.h>
#endif
#include <string>
using namespace std;
bool bCanLog = false;
// 从这里开始的代码都不是关键代码
inline string current_exact_time ()
{
	char szTime[128] = {0};
#if defined(WINDOWS)
	SYSTEMTIME st; 
	GetLocalTime(&st); 
	_snprintf(szTime, sizeof(szTime), "%04d-%02d-%02d %02d:%02d:%02d:%03d", 
		st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond, st.wMilliseconds);
#else
	time_t tmGmt = {0};
	struct tm* tmBeijing = NULL;
	time(&tmGmt);
	tmBeijing = localtime(&tmGmt);
	timeval curTime;
	gettimeofday(&curTime, NULL);
	int mill = curTime.tv_usec / 1000;
	snprintf(szTime, sizeof(szTime), "%04d-%02d-%02d %02d:%02d:%02d:%03d", (1900+tmBeijing->tm_year),(1+tmBeijing->tm_mon),tmBeijing->tm_mday,
		tmBeijing->tm_hour,tmBeijing->tm_min,tmBeijing->tm_sec, mill);
#endif
	return string(szTime);
}
inline void print_line(int line, const char* file, const char* format, ...) {
	if (!bCanLog) {
		return;
	}
    va_list args;
    va_start(args, format); 
    char szBuf[2048] = {0};
    vsnprintf(szBuf, 2048, format, args); 
    va_end(args);
#if defined WINDOWS
    int tid = GetCurrentThreadId(); 
#else
    pthread_t tid = pthread_self(); 
#endif
	int pid = getpid();
    printf("[%s][%d][0x%x]: %s -- %s:%d\n", current_exact_time().c_str(), pid, tid, szBuf, file, line);
}
#define msg_print(...) print_line(__LINE__, __FILE__, __VA_ARGS__);
#define _safe_delete(ptr) if((ptr) != 0) {delete (ptr); (ptr) = 0;}
// 非关键代码结束,下面开始的都是关键代码
class org_empty_parent {
public:
    org_empty_parent() {
        msg_print("org_empty_parent() \tthis[%p]", this); 
    }
};
class non_empty_parent {
public:
    non_empty_parent() {
        msg_print("non_empty_parent() \tthis[%p]", this); 
    }
private:
    int data;
}; 
class virtual_parent {
public:
    virtual_parent() {
        msg_print("virtual_parent() \tthis[%p]", this);
    }
	virtual string get_date() = 0;
};
class child_0 : public org_empty_parent {
public:
    child_0() {
        msg_print("[group1]child_0() \tthis[%p]", this);
    }
}; 
class child_1 : public virtual_parent {
public:
    child_1() {
        msg_print("[group1]child_1() \tthis[%p]", this); 
    }
    string get_date() {
        return current_exact_time();
    }
}; 
class child_2 : public org_empty_parent, public virtual_parent {
public:
    child_2() {
        msg_print("[group1]child_2() \tthis[%p]", this); 
    }
    string get_date() {
        return current_exact_time();
    }
}; 
class child_3 : public non_empty_parent {
public:
    child_3() {
        msg_print("[group2]child_3() \tthis[%p]", this); 
    }
}; 
class child_4 : public non_empty_parent, public virtual_parent {
public:
    child_4() {
        msg_print("[group2]child_4() \tthis[%p]", this); 
    }
    string get_date() {
        return current_exact_time();
    }
}; 
int main (int argc, char* argv[]) {
    bCanLog = true;

    child_0 *p0 = new child_0; 
    
    printf("\n--\n\n");
    
    child_1 *p1 = new child_1; 
    
    printf("\n--\n\n");
    
    child_2 *p2 = new child_2;
    
    printf("\n--\n\n");
    child_3 *p3 = new child_3; 
    
    printf("\n--\n\n");
    child_4 *p4 = new child_4;
    
    _safe_delete(p0); 
    _safe_delete(p1); 
    _safe_delete(p2);
    _safe_delete(p3); 
    _safe_delete(p4); 
    return 0;
}

其中child0~child2为第一组:group1, child3~child4为第二组:group2
linux的输出结果:
C++ 多继承 父类是虚基类和非虚基类时 父类指针值问题
可以看到:
1、多继承时,当一个基类有虚函数,另一个基类没有成员变量,全部基类和子类的this都是相同的(如group1的输出)
2、多继承时,当一个基类有虚函数,另一基类有成员变量,这个有成员变量的基类的this和子类的this就不想同了。(group2的输出)
windows的输出结果:
C++ 多继承 父类是虚基类和非虚基类时 父类指针值问题
可以看到:
只要是多继承,其中一个基类有虚函数,另一个基类不管有没有成员变量,没有虚函数的那个基类的this和子类就不相同。(group1的child3的输出和group2的child4的输出)
本人的问题是:
1、这种不相同是什么导致的,是C++的规则还是编译器,具体是哪个知识点,该怎么解释
2、windows和linux的差异:linux只有group2参会出现this的差异,而windows的group1和2的都出现了差异,这怎么解释
本人的测试环境:
linux:
1、CentOS release 6.4 (Final)
2、gcc version 4.7.0 (GCC)
windows:
1、win 7 ultimate X64
2、VS2008 版本信息:
Microsoft Visual Studio 2008
Version 9.0.30729.1 SP
Installed Edition: Enterprise
Microsoft Visual C++ 2008   91899-153-0000007-60931
Microsoft Visual C++ 2008

解决方案

60

《深度探索C++对象模型》
《C++反汇编与逆向分析技术揭秘》

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明C++ 多继承 父类是虚基类和非虚基类时 父类指针值问题
喜欢 (0)
[1034331897@qq.com]
分享 (0)