将 class 转换为仅添加附加功能的派生 class 是否安全?
Is it safe to cast a class to a derived class that just adds additional functions?
我有一个包含大量数据的 class。根据情况,我需要以不同的方式输出这些数据。我希望将每种情况的输出例程分开,并且我希望保持基础 class 干净。
转换为不添加任何数据成员而仅添加非虚函数的派生 class 是否绝对安全?
#include <stdio.h>
class Base {
public:
Base() { printf("Base()\n"); }
double A = 3.14;
int B = 5;
int C = 42;
};
class Derived1 : public Base {
public:
Derived1() { printf("Derived1()\n"); }
void DoStuff() {
// doing stuff with base class's data
printf(" A = %.4f\n", A);
printf(" B = %d\n", B);
printf(" C = %d\n", C);
}
};
class Derived2 : public Base {
public:
Derived2() { printf("Derived2()\n"); }
void DoStuff() {
// doing stuff with base class's data in a slightly different way
printf(" A = %.4f, B = %d, C = %d\n", A, B, C);
}
};
class OtherBase {
public:
OtherBase() { printf("OtherBase()\n"); }
int D = 10;
};
class Derived3 : virtual public OtherBase, virtual public Base {
public:
Derived3() { printf("Derived3()\n"); }
void SomeFunction() {
A = 6.28;
B = 1;
C = 500;
printf("Done some other stuff.\n");
}
};
int main() {
printf("Base class\n\n");
Base* Instance = new Base();
printf("Cast to Derived1:\n");
static_cast<Derived1*>(Instance)->DoStuff();
printf("Cast to Derived2:\n");
static_cast<Derived2*>(Instance)->DoStuff();
printf("\nOther class derived from base class\n\n");
Derived3* Instance2 = new Derived3();
Instance2->SomeFunction();
printf("Cast to Derived1:\n");
static_cast<Derived1*>(static_cast<Base*>(Instance2))->DoStuff();
printf("Cast to Derived2:\n");
static_cast<Derived2*>(static_cast<Base*>(Instance2))->DoStuff();
printf("c-style cast to Derived1:\n");
((Derived1*) Instance2)->DoStuff();
printf("c-style cast to Derived2:\n");
((Derived2*) Instance2)->DoStuff();
return 0;
}
class“Derived3”(具有“Base”的虚拟继承)首先转换为“Base”然后转换为“Derived1”/“Derived2”的部分对我来说看起来不太好但我知道 C ++ 社区如何不赞成 C 风格的转换。然而,在这个小例子中,c 风格的转换正在编译并且工作得很好:
我知道多重继承存在问题,其中一个基础 classes 的转换可以具有与从中转换继承的 class 不同的指针地址。所以我明白依赖它可能太危险了。
我在顶部示例中执行的静态转换安全吗?
不,这不安全。程序的行为未定义。
仅当对象的动态类型是该派生类型(或进一步的派生类型)时,静态转换为派生类型才是安全的。
我有一个包含大量数据的 class。根据情况,我需要以不同的方式输出这些数据。我希望将每种情况的输出例程分开,并且我希望保持基础 class 干净。
转换为不添加任何数据成员而仅添加非虚函数的派生 class 是否绝对安全?
#include <stdio.h>
class Base {
public:
Base() { printf("Base()\n"); }
double A = 3.14;
int B = 5;
int C = 42;
};
class Derived1 : public Base {
public:
Derived1() { printf("Derived1()\n"); }
void DoStuff() {
// doing stuff with base class's data
printf(" A = %.4f\n", A);
printf(" B = %d\n", B);
printf(" C = %d\n", C);
}
};
class Derived2 : public Base {
public:
Derived2() { printf("Derived2()\n"); }
void DoStuff() {
// doing stuff with base class's data in a slightly different way
printf(" A = %.4f, B = %d, C = %d\n", A, B, C);
}
};
class OtherBase {
public:
OtherBase() { printf("OtherBase()\n"); }
int D = 10;
};
class Derived3 : virtual public OtherBase, virtual public Base {
public:
Derived3() { printf("Derived3()\n"); }
void SomeFunction() {
A = 6.28;
B = 1;
C = 500;
printf("Done some other stuff.\n");
}
};
int main() {
printf("Base class\n\n");
Base* Instance = new Base();
printf("Cast to Derived1:\n");
static_cast<Derived1*>(Instance)->DoStuff();
printf("Cast to Derived2:\n");
static_cast<Derived2*>(Instance)->DoStuff();
printf("\nOther class derived from base class\n\n");
Derived3* Instance2 = new Derived3();
Instance2->SomeFunction();
printf("Cast to Derived1:\n");
static_cast<Derived1*>(static_cast<Base*>(Instance2))->DoStuff();
printf("Cast to Derived2:\n");
static_cast<Derived2*>(static_cast<Base*>(Instance2))->DoStuff();
printf("c-style cast to Derived1:\n");
((Derived1*) Instance2)->DoStuff();
printf("c-style cast to Derived2:\n");
((Derived2*) Instance2)->DoStuff();
return 0;
}
class“Derived3”(具有“Base”的虚拟继承)首先转换为“Base”然后转换为“Derived1”/“Derived2”的部分对我来说看起来不太好但我知道 C ++ 社区如何不赞成 C 风格的转换。然而,在这个小例子中,c 风格的转换正在编译并且工作得很好:
我知道多重继承存在问题,其中一个基础 classes 的转换可以具有与从中转换继承的 class 不同的指针地址。所以我明白依赖它可能太危险了。
我在顶部示例中执行的静态转换安全吗?
不,这不安全。程序的行为未定义。
仅当对象的动态类型是该派生类型(或进一步的派生类型)时,静态转换为派生类型才是安全的。