我想做这样的事情:
template <int N, typename type>
class BaseClass{
public:
type array[N];
};
template <typename type>
class Derived : public BaseClass <1, type>{
public:
type &alias = ( BaseClass<1, type>::array[0] );
};
但是当我使用时:
cout << sizeof( Derived <char> ) << endl;
它打印出16,我希望它打印1或5,而不是16.有没有办法这样做只需要sizeof(array[N])
?为什么16?当我将BaseClass<1, type>
更改为BaseClass<3, type>
时,它也打印出16。
编辑:
我找到了解决这个问题的方法:
基类:
template <typename container, int N>
class BaseClass : public container {
public:
// constructor example
BaseClass(){
for(int i = 0; i < N; i++)
container::array[i] = 0;
}
// function examples
BaseClass operator+( const BaseClass& arg ){
BaseClass result;
for( int i = 0; i < N; i++ )
result.array[i] = container::array[i] + arg.array[i];
return result;
}
friend ostream& operator << ( ostream& stream, const BaseClass& arg ){
for( int i = 0; i < N; i++ )
stream << arg.array[i] << ' ';
return stream;
}
};
对于派生类我会使用这样的东西:
template <typename type>
class container3{
public:
union{
type array[3];
struct{
type x;
type y;
type z;
} ;
};
};
class Derived : public BaseClass< container3<float>, 3 >{
public:
Derived( float x = 0, float y = 0, float z = 0 ){
this->x = x;
this->y = y;
this->z = z;
}
};
现在我可以像这样使用它们:
Derived var1( 1, 2 );
Derived var2;
var2.y = 3;
var2.z = 6;
cout << var2 + var1 << endl;
cout << sizeof( Derived ) << endl; /// this prints 12
return 0;
答案 0 :(得分:1)
为什么打印16?
首先,这是实现定义。但这是一个似是而非的解释。
派生类中的引用会花费您指针的大小,在64位平台上,该指针可能是8个字节。基类中的1 char
数组会花费您额外的字节。但是,由于对齐限制,编译器将1 + 8舍入到16,因为您的平台可能喜欢将地址对齐到8个字节。
我该怎么办?
摆脱参考。如果它总是指向基类中的数组,则不需要将其存储为成员。如果您认为每次拼写BaseClass<1, type>::array[0]
都是太多输入,您可以添加成员函数。
type&
getit() noexcept
{
return BaseClass<1, type>::array[0];
}
这不会增加您的对象大小。您可能还需要const
重载。
答案 1 :(得分:0)
不是没有增加对象的大小,没有。
但是你可以写一个做同样事情的方法,并在你使用引用的任何地方调用该方法。它将在使用优化编译时进行内联,并且与别名相比不应导致更多开销(或任何开销,如果公共子表达式消除传递足够好,它将在您的示例中,因为别名表达式是尽可能简单。)
template <typename type>
class Derived : public BaseClass <1, type>{
public:
type& alias() { return array[0]; }
type const& alias() const { return array[0]; }
};
对象大小为16的原因是编译器创建的结构填充为机器字大小的倍数。这允许您创建此类结构的数组,而不必担心奇怪的对齐(并且实例之间没有间隙)。
我怀疑你的机器字大小是8字节(64位CPU)。因此,引用alias
的8个字节(实际上只是指针周围的特殊语法),加上array
的一个字节,加上7个字节的填充,使其达到8的倍数。 / p>
答案 2 :(得分:0)
根据C ++标准,未指定引用是否占用存储空间。因此,您只能通过尝试并查看会发生什么来调查此案例。
拥有类的引用成员意味着默认生成的复制构造函数,移动构造函数和赋值运算符不会正常工作。所以这给你的班级带来了相当大的复杂性。
当然你可以写:
type &alias() { return BaseClass<1, type>::array[0]; }
不会占用存储空间。