这段 C++ 代码的安全性和独立于编译器的程度如何?
How safe and compiler-independent is this C++ code?
我创建了一些对我来说很奇怪的代码,但似乎可以满足我的要求。但是,我不确定它的平台独立性或它的安全性,或者是否有更简单的方法来做我想做的事情。
我正在阅读 Curiously Recurring Template Program (on wikipedia),其中有一个 class 计数器的示例代码,它让每个派生的 class 跟踪有多少实例已经通过从具有该功能的基础继承而创建。
我一直在寻找方法来导出 classes 对公共对象的引用(通过指针),而不必添加静态变量并为每个新 class 定义虚函数我创造。 (我计划创建很多派生的 classes。)但是,派生的 classes,因为它们是用模板创建的,被认为与基础不同,所以它们不能隐式转换为一个基指针。
Dynamic_cast 和 static_cast 没有用,所以我尝试了 reinterpret_cast,为了好玩,看看有什么行为。它最终显示了基 class 中的静态变量,这不是我想要的,但它让我想起了我以前在静态和虚函数方面的经验(长话短说)。我在基础 class 中写了一个虚函数,虚函数为派生的 classes 报告了正确的变量,多态性盟友。
它有效,至少根据 codepad.org,但我仍然不确定它的平台一致性或 reinterpret_cast 在这种情况下的安全性。比我更有经验的人可以解释一下为什么这样做吗?
这是我的代码。它看起来像维基百科示例代码,因为它原来就是这样。
#include <iostream>
using namespace std;
template <typename T>
class counter
{
public:
static int separateObject;
virtual void printStatic(){
cout << this->separateObject << endl;
}
};
template <typename T> int counter<T>::separateObject( 0 );
class X : public counter<X>
{
// ...
};
class Y : public counter<Y>
{
// ...
};
typedef counter<void*>* voidcounter;
int main(){
X* counterX = new X;
Y* counterY = new Y;
counterX->separateObject = 9001;
counterY->separateObject = 42;
cout << "Object Xs value is: " << counterX->separateObject << endl;
cout << "Object Ys value is: " << counterY->separateObject << endl;
voidcounter polycount = reinterpret_cast<voidcounter>(counterX);
polycount->printStatic();
polycount = reinterpret_cast<voidcounter>(counterY);
polycount->printStatic();
return 0;
}
I had been looking for ways to have derived classes reference to a common object
那就别用CRTP了。 CRTP 适用于当您需要所有基本类型不通用时(这允许每种类型都有自己的计数器)。这 100% 正是它的用途。如果你想要一个共享的公共基础,使用一个普通的虚拟基础class。您不能使用 static_cast
或 dynamic_cast
,因为它们没有共同的基础。你用 reinterpret_cast
做的事情非常不安全,因为它是未定义的行为。
class shared_counter_base {
virtual ~shared_counter_base(){}
virtual void printStatic()=0;
};
template <typename T>
class counter : shared_counter_base
{
public:
static int separateObject;
virtual void printStatic() {
cout << this->separateObject << endl;
}
};
template <typename T> int counter<T>::separateObject( 0 );
class X : public counter<X>
{
// ...
};
class Y : public counter<Y>
{
// ...
};
int main(){
X* counterX = new X;
Y* counterY = new Y;
counterX->separateObject = 9001;
counterY->separateObject = 42;
cout << "Object Xs value is: " << counterX->separateObject << endl;
cout << "Object Ys value is: " << counterY->separateObject << endl;
shared_counter_base polycount = counterX;
polycount->printStatic();
polycount = counterY;
polycount->printStatic();
return 0;
}
我创建了一些对我来说很奇怪的代码,但似乎可以满足我的要求。但是,我不确定它的平台独立性或它的安全性,或者是否有更简单的方法来做我想做的事情。
我正在阅读 Curiously Recurring Template Program (on wikipedia),其中有一个 class 计数器的示例代码,它让每个派生的 class 跟踪有多少实例已经通过从具有该功能的基础继承而创建。
我一直在寻找方法来导出 classes 对公共对象的引用(通过指针),而不必添加静态变量并为每个新 class 定义虚函数我创造。 (我计划创建很多派生的 classes。)但是,派生的 classes,因为它们是用模板创建的,被认为与基础不同,所以它们不能隐式转换为一个基指针。
Dynamic_cast 和 static_cast 没有用,所以我尝试了 reinterpret_cast,为了好玩,看看有什么行为。它最终显示了基 class 中的静态变量,这不是我想要的,但它让我想起了我以前在静态和虚函数方面的经验(长话短说)。我在基础 class 中写了一个虚函数,虚函数为派生的 classes 报告了正确的变量,多态性盟友。
它有效,至少根据 codepad.org,但我仍然不确定它的平台一致性或 reinterpret_cast 在这种情况下的安全性。比我更有经验的人可以解释一下为什么这样做吗?
这是我的代码。它看起来像维基百科示例代码,因为它原来就是这样。
#include <iostream>
using namespace std;
template <typename T>
class counter
{
public:
static int separateObject;
virtual void printStatic(){
cout << this->separateObject << endl;
}
};
template <typename T> int counter<T>::separateObject( 0 );
class X : public counter<X>
{
// ...
};
class Y : public counter<Y>
{
// ...
};
typedef counter<void*>* voidcounter;
int main(){
X* counterX = new X;
Y* counterY = new Y;
counterX->separateObject = 9001;
counterY->separateObject = 42;
cout << "Object Xs value is: " << counterX->separateObject << endl;
cout << "Object Ys value is: " << counterY->separateObject << endl;
voidcounter polycount = reinterpret_cast<voidcounter>(counterX);
polycount->printStatic();
polycount = reinterpret_cast<voidcounter>(counterY);
polycount->printStatic();
return 0;
}
I had been looking for ways to have derived classes reference to a common object
那就别用CRTP了。 CRTP 适用于当您需要所有基本类型不通用时(这允许每种类型都有自己的计数器)。这 100% 正是它的用途。如果你想要一个共享的公共基础,使用一个普通的虚拟基础class。您不能使用 static_cast
或 dynamic_cast
,因为它们没有共同的基础。你用 reinterpret_cast
做的事情非常不安全,因为它是未定义的行为。
class shared_counter_base {
virtual ~shared_counter_base(){}
virtual void printStatic()=0;
};
template <typename T>
class counter : shared_counter_base
{
public:
static int separateObject;
virtual void printStatic() {
cout << this->separateObject << endl;
}
};
template <typename T> int counter<T>::separateObject( 0 );
class X : public counter<X>
{
// ...
};
class Y : public counter<Y>
{
// ...
};
int main(){
X* counterX = new X;
Y* counterY = new Y;
counterX->separateObject = 9001;
counterY->separateObject = 42;
cout << "Object Xs value is: " << counterX->separateObject << endl;
cout << "Object Ys value is: " << counterY->separateObject << endl;
shared_counter_base polycount = counterX;
polycount->printStatic();
polycount = counterY;
polycount->printStatic();
return 0;
}