首页 > 代码库 > 模板与继承之艺术——空基类优化
模板与继承之艺术——空基类优化
1、概念
C++中有“空”类的概念,这就意味着在运行期间其内部不好任何内存。
只包含类型的成员函数、非虚成员函数和静态数据成员的类为空类。
非静态的数据成员,虚函数和虚基类则在运行时期消耗存储空间。
2、空基类优化如下:
#include<iostream>
using namespace std;
class Empty{
typedef int Int;
};
class EmptyToo : public Empty
{};
class EmptyThree : public EmptyToo
{};
int main()
{
cout << "sizeof(Empty):" << sizeof(Empty) << endl;
cout << "sizeof(EmptyToo):" << sizeof(EmptyToo)<< endl;
cout << "sizeof(EmptyThree):" << sizeof(EmptyThree) << endl;
}
(1)在类EmptyToo中类Empty没有分配存储空间
(2)带有优化空基类的空类作为被继承的基类(没有其他基类时,单继承)时,其大小也为0,这也就是EmptyTree 能和Empty具有相同大小的原因所在。
3、如果有其他基类时:
#include<iostream>
class Empty{
typedef int Int;
};
class EmptyToo : public Empty{};
class EmptyThree : public Empty, public EmptyToo{};
int main()
{
cout << "sizeof(Empty):"<< sizeof(Empty) << endl; //输出1
cout << "sizeof(EmptyToo)" << sizeof(EmptyToo)<< endl; //输出1
cout << "sizeof(EmptyThree):" << sizeof(EmptyThree) << endl; //输出2
}
如果继承时是多重继承:
EmptyThree中有两个不同的子类Empty对象,一个是直接继承来的Empty对象,另一个是EmptyToo继承来的Empty对象。
由于是两个对象所以不能让其有相同的地址空间。即这里优化(2)不起作用,EmptyThree是两个Empty和EmptyToo大小之和。
4、将成员作为基类
只举一例,模板参数确定会被实例化为类型(不是非类型,不是原生类型比如int),该模板类的另一个成员类型不是空类。如下:
template<typename CustomClass>
class Optimizable{
private:
CustomClass info;
void* storage;
};
改写为:
template <typename CustomClass>
class Optimizable {
private:
BaseMemberPair<CustomClass, void*> info_and_storage;
};
//
template<typename Base, typename Member>
class BaseMemberPair : private Base{
private:
Member member;
public:
BaseMemberPair(Base const &b, Member const &m):Base(b), member(m){}
//通过first来访问基类数据
Base const& first() const{ return (Base const&)*this; }
Base& first() const { return (Base&)*this; }
//通过second()来访问成员变量
Member const& second() const { return this->member; }
Member& second() const { return this->member; }
};
优化前:
#include<iostream>using namespace std;template<typename CustomClass>class Optimizable{ private: CustomClass info; void* storage;};class Test{};int main(){ cout << sizeof(Optimizable<Test>) << endl; //结果为8 return 0;}
优化后:
#include<iostream>using namespace std;template<typename Base, typename Member>class BaseMemberPair : private Base{ private: Member member;public: BaseMemberPair(Base const &b, Member const &m):Base(b), member(m){}//通过first来访问基类数据Base const& first() const{ return (Base const&)*this; } //提供给const对象调用Base& first() { return (Base&)*this; }//通过second()来访问成员变量Member const& second() const { return this->member; }Member& second() { return this->member; }};template <typename CustomClass>class Optimizable { private: BaseMemberPair<CustomClass, void*> info_and_storage;};class Test{};int main(){ cout << sizeof(Optimizable<Test>) << endl;//结果为4 return 0;}
5、警告:
针对下面的情况:
template<typename T1, typename T2>
class MyClass{
private:
T1 a;
T2 b;
};
//优化
template<typename T1, typename T2>
class MyClass : private T1, private T2{};
在不知道T1和T2是否为类型的情况下,最好不要盲目使用上面的优化方法,因为:
(1)此方法不适用于原生类型int等
(2)如果T1, 和T2的类型相同继承会出问题。
(3)增加基类会改变接口,因为多重继承,如果T1和T2都有共同的基类Base的话,那么MyClass中的数据成员,成员函数将会有二义性。所以此方法最好适应是之前提演示出的情况。
编辑整理:Claruarius,转载请注明出处。
模板与继承之艺术——空基类优化
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。