【20090915】C++培训日记-模块化编程
下面是demo。。使用时请注意VS中包含文件目录和附加库目录的设定,或直接将对应的h、lib、dll拷贝到使用工程的目录下。
【20090914】C++培训日记-MFC
missing type specifier
写DataLoader的时候 在cpp中总是报这个错。。吐血,调用的类也一直提示未定义的类型。。
最后发现是.h中类声明最后忘了加分号 OrOrOrz。。
【20090904】C++培训日志-ini操作
rt。话说这篇日志是17号写的 囧。
////////////////////////////////////////////////////////////////////////// // CopyRight(c) 2009, YOYO, All Rights Reserved. // Author: LIN YiQian // Created: 2009/09/17 // Describe: INI文件读取练习 ////////////////////////////////////////////////////////////////////////// #include <Windows.h> #include <iostream> void main(void) { // 读整数 UINT nResult = GetPrivateProfileInt("pic", "count", 0, ".//config.ini"); std::cout << nResult << std::endl; // 读文本 char szStr[256]; memset(szStr, 0, sizeof(szStr)); GetPrivateProfileString("string", "Display", "", szStr, sizeof(szStr), ".//config.ini"); std::cout << szStr << std::endl; // 写文本 WritePrivateProfileString("YOYO", "name", "linyq", ".//config.ini"); // 写段 WritePrivateProfileSection("CLASS", "company=tq\0date=20090817\0number=48\0", ".//config.ini"); // 读取段 GetPrivateProfileSection("CLASS", szStr, sizeof(szStr), ".//config.ini"); char* p = szStr; while (p != NULL) { std::cout << p << std::endl; p = strtok(p + strlen(p) + 1, "\0"); } system("pause"); return; }
【20090824】C++培训日记-STL扫盲
今天是几个常用容器的基本使用。。于是放几个DEMO上来:
包括 vector, deque, list, map, multimap, set, multiset, stack, queue,以及较少用到的valarray, bitset, priority_queue
通过虚函数表访问private成员
通过虚函数表可以访问到对象的布局,通过函数指针可以运行函数,不论是private还是public,于是单继承、非virtual的demo如下:
-
#include <iostream>
-
-
class A
-
{
-
public:
-
A(): x(5) { }
-
-
private:
-
virtual void fun() { std::cout << "A::fun()" << std::endl; }
-
-
private:
-
int x;
-
};
-
-
class B: public A
-
{
-
public:
-
B(): y(3) { }
-
-
private:
-
virtual void fun() { std::cout << "B::fun()" << std::endl; }
-
-
private:
-
int y;
-
};
-
-
typedef void (*Fun)();
-
-
void PrintVTable(Fun* pVT)
-
{
-
Fun* pFun = pVT;
-
while( *pFun )
-
{
-
(*pFun)();
-
pFun ++;
-
}
-
}
-
-
void PrintMembers(int* pMembers)
-
{
-
std::cout << *pMembers << std::endl;
-
}
-
-
void PrintVTableAndMembers(B* ptr)
-
{
-
int* pAddress = (int*) ptr;
-
PrintVTable((Fun*) *pAddress);
-
pAddress ++;
-
-
PrintMembers(pAddress);
-
pAddress ++;
-
-
PrintMembers(pAddress);
-
pAddress ++;
-
}
-
-
void main(void)
-
{
-
B b;
-
-
PrintVTableAndMembers(&b);
-
-
system("pause");
-
}
如果是多继承 或者 继承方式用virtual,对象的布局是不一样的,可以参考下本文:http://yoyo.is-programmer.com/posts/10671.html
多重继承的虚函数表与类型转换
总结:
- 非virtual继承:
进行隐式转换或进行显式转换均可时(代码中简写为隐式强转),最左父类指针指向子类时指向地址不变,其他父类指针指向子类时指向地址需要偏移,根据指针的类型对虚函数进行地址偏移(访问指针类型对象的虚函数表)。
必须进行显式转换时指针指向地址均不变,按照强制转换前的类型对虚函数进行地址偏移(访问原来类型的虚函数表)。
但是它们的实际函数都是访问子类的实际虚函数。
- virtual继承:
进行隐式转换或进行显式转换均可时(代码中简写为隐式强转),指针指向子类时指向地址均需要偏移,根据指针的类型对虚函数进行地址偏移(访问指针类型对象的虚函数表)。
必须进行显式转换时指针指向地址均不变,按照强制转换前的类型对虚函数进行地址偏移(访问原来类型的虚函数表)。
但是它们的实际函数都是访问子类的实际虚函数。
virtual继承与非virtual继承的差别其实仅在于不需要显式转换时的最左父类指针是否偏移。这与当时的虚函数表布局方式有关。
virtual继承将新的virtual方法都写在自身vftable中; 而非virtual继承则将新的virtual方法更新到最左父类的vftable中。
【20090821】C++培训日记-虚函数表
检测方法(VS2005):项目命令行加上参数/d1reportAllClassLayout,在编译时CTRL+F5搜索输出,查看类的对象布局。
vftable - 虚函数表; vbtable - 虚继承的父类表; member - 类的成员变量(这个只是写作方便说明 = =)。
总结:
- 继承方式:非virtual继承:导入各个父类的结构(按照父类声明的顺序,从上到下),自身member在最后
- 重写virtual方法:更新该方法最早定义的类的vftable
- 新的virtual方法:在最左父类的vftable增加
- 继承方式:有virtual继承:在自身member后增加virtual父类的结构(按照子类继承的顺序从左到右),同时在最前面增加vbtable(如果没有的话),增加一项指向父类结构
- 重写virtual方法:更新该方法的最早定义的类的vftable
- 新的virtual方法:在自身最前面增加vftable(如果没有的话),在自己的vftable增加