使用数组的对象的编译时多态性是否可能?
Is Compile Time Polymorphism Of Objects Using Arrays Possible?
我还在学习,我有一个问题希望有人能帮助我:
是否可以在不使用虚函数的情况下实现从同一基 class 继承的不同 class 的编译时多态性,以便在数组中使用?
任何对 C++ 有一点 OOP 了解的人,如果你有类似的东西
class Base {
public:
virtual void foo (){
std::cout << "I'm the base" << std::endl;
}
}
class A : public Base {
public:
void foo() {
std::cout << "I'm the child" << std::endl;
}
}
class B : public Base {
public:
void foo() {
std::cout << "I'm the child #2" << std::endl;
}
}
//Assume some main here
A *a = new A();
B *b = new B();
Base *someArray[] = {a,b};
someArray[0]->foo(); //"I'm the child"
someArray[1]->foo(); //"I'm the child #2"
我们知道这是可行的,因为函数和继承已解决 运行-时间。但是我要知道的是如何在没有虚函数的情况下做到这一点,或者是否可以在不使用虚函数的情况下做同样的事情?
假设你做这样的事情
class Base {
public:
void foo (){
std::cout << "I'm the base" << std::endl;
}
}
class A : public Base {
public:
void foo() {
std::cout << "I'm the child" << std::endl;
}
}
class B : public Base {
public:
void foo() {
std::cout << "I'm the child #2" << std::endl;
}
}
//Assume some main here
A *a = new A();
B *b = new B();
Base *someArray[] = {a,b};
someArray[0]->foo(); //"I'm the base"
someArray[1]->foo(); //"I'm the base"
所以有很多选择,但我似乎无法找到与我想要的行为相同的东西。我读到的一种解决方案是制作一个静态 class 模板,其工作方式类似于
template <class T>
class Base
{
public:
void interface()
{
// ...
static_cast<T*>(this)->implementation();
// ...
}
static void static_func()
{
// ...
T::static_sub_func();
// ...
}
};
class Derived : Base<Derived>
{
public:
void implementation() {
std::cout << "I am derived" << std::endl;
}
static void static_sub_func();
};
class AlsoDerived : Base<Derived>
{
public:
void implementation() {
std::cout << "I am also derived" << std::endl;
}
static void static_sub_func();
};
//Assume in some main
Derived div;
AlsoDerived alsoDiv;
Derived *someArray[] = { &div, &alsoDiv };//does not work not the same type
Base *someArray[] = { &div, &alsoDiv }; //does not work b/c its a template
以上不是我想要的行为。然后是看起来很有希望的静态转换,但是我需要知道 class 在任何给定时间它会是什么,这不是我想要的行为。
class Base {
public:
void foo (){
std::cout << "I'm the base" << std::endl;
}
}
class A : public Base {
public:
void foo() {
std::cout << "I'm the child" << std::endl;
}
}
class B : public Base {
public:
void foo() {
std::cout << "I'm the child #2" << std::endl;
}
}
//Assume some main here
A *a = new A();
A *b = new A();
B *c = new B();
Base *someArray[] = {a,b,c};
someArray[0]->foo(); //"I'm the base"
static_cast<A*>(someArray[1])->foo(); //"I'm the child"
static_cast<B*>(someArray[2])->foo(); //"I'm the child #2"
这非常接近我想要的但是我的问题是 static_cast 工作我需要知道什么 class 我想要静态案例而不是我想要的行为.
你怎么看?有没有更好的方法做我想做的事?
感谢阅读,如果对我的问题有任何困惑,请告诉我,以便我澄清。
没有真正的方法可以在编译时做你想做的事。仅仅是因为您希望您的行为取决于 运行 时间的对象类型。
C++ 通过多态性提供 运行 时间类型依赖行为,即使用虚函数,如果需要,RTTI。如果您不想使用此 "natural way",您可以选择以下选项:
- 您在编译时知道对象的类型(例如,如果您确定第一个元素始终是
A*
,第二个元素始终是 B*
):在这种情况下您可以像第三种情况一样使用 static_cast
,或者使用模板化代码(例如,如果您更喜欢 compile-time policies rather than run-time strategies)。但它通常不是处理容器中随机对象的方式。
- 你可以自己找出对象的类型并推断出相应的函数来调用:一个典型的方法是在基 class 中有一个输入字段并用它来向下转换用
static_cast
。但这不是最佳做法。添加您自己的类似 RTTI 的功能而不是使用编译器的优化功能不会比多态更有效。
- 您可以使用
std::variant
or a std::any
:这些提供了使用编译时功能提供某种 运行 时间相关行为的可能性(不一定要求从共同基础)。
剩下的问题是,如果需要,为什么要避免正常的多态性。
我还在学习,我有一个问题希望有人能帮助我:
是否可以在不使用虚函数的情况下实现从同一基 class 继承的不同 class 的编译时多态性,以便在数组中使用?
任何对 C++ 有一点 OOP 了解的人,如果你有类似的东西
class Base {
public:
virtual void foo (){
std::cout << "I'm the base" << std::endl;
}
}
class A : public Base {
public:
void foo() {
std::cout << "I'm the child" << std::endl;
}
}
class B : public Base {
public:
void foo() {
std::cout << "I'm the child #2" << std::endl;
}
}
//Assume some main here
A *a = new A();
B *b = new B();
Base *someArray[] = {a,b};
someArray[0]->foo(); //"I'm the child"
someArray[1]->foo(); //"I'm the child #2"
我们知道这是可行的,因为函数和继承已解决 运行-时间。但是我要知道的是如何在没有虚函数的情况下做到这一点,或者是否可以在不使用虚函数的情况下做同样的事情?
假设你做这样的事情
class Base {
public:
void foo (){
std::cout << "I'm the base" << std::endl;
}
}
class A : public Base {
public:
void foo() {
std::cout << "I'm the child" << std::endl;
}
}
class B : public Base {
public:
void foo() {
std::cout << "I'm the child #2" << std::endl;
}
}
//Assume some main here
A *a = new A();
B *b = new B();
Base *someArray[] = {a,b};
someArray[0]->foo(); //"I'm the base"
someArray[1]->foo(); //"I'm the base"
所以有很多选择,但我似乎无法找到与我想要的行为相同的东西。我读到的一种解决方案是制作一个静态 class 模板,其工作方式类似于
template <class T>
class Base
{
public:
void interface()
{
// ...
static_cast<T*>(this)->implementation();
// ...
}
static void static_func()
{
// ...
T::static_sub_func();
// ...
}
};
class Derived : Base<Derived>
{
public:
void implementation() {
std::cout << "I am derived" << std::endl;
}
static void static_sub_func();
};
class AlsoDerived : Base<Derived>
{
public:
void implementation() {
std::cout << "I am also derived" << std::endl;
}
static void static_sub_func();
};
//Assume in some main
Derived div;
AlsoDerived alsoDiv;
Derived *someArray[] = { &div, &alsoDiv };//does not work not the same type
Base *someArray[] = { &div, &alsoDiv }; //does not work b/c its a template
以上不是我想要的行为。然后是看起来很有希望的静态转换,但是我需要知道 class 在任何给定时间它会是什么,这不是我想要的行为。
class Base {
public:
void foo (){
std::cout << "I'm the base" << std::endl;
}
}
class A : public Base {
public:
void foo() {
std::cout << "I'm the child" << std::endl;
}
}
class B : public Base {
public:
void foo() {
std::cout << "I'm the child #2" << std::endl;
}
}
//Assume some main here
A *a = new A();
A *b = new A();
B *c = new B();
Base *someArray[] = {a,b,c};
someArray[0]->foo(); //"I'm the base"
static_cast<A*>(someArray[1])->foo(); //"I'm the child"
static_cast<B*>(someArray[2])->foo(); //"I'm the child #2"
这非常接近我想要的但是我的问题是 static_cast 工作我需要知道什么 class 我想要静态案例而不是我想要的行为.
你怎么看?有没有更好的方法做我想做的事?
感谢阅读,如果对我的问题有任何困惑,请告诉我,以便我澄清。
没有真正的方法可以在编译时做你想做的事。仅仅是因为您希望您的行为取决于 运行 时间的对象类型。
C++ 通过多态性提供 运行 时间类型依赖行为,即使用虚函数,如果需要,RTTI。如果您不想使用此 "natural way",您可以选择以下选项:
- 您在编译时知道对象的类型(例如,如果您确定第一个元素始终是
A*
,第二个元素始终是B*
):在这种情况下您可以像第三种情况一样使用static_cast
,或者使用模板化代码(例如,如果您更喜欢 compile-time policies rather than run-time strategies)。但它通常不是处理容器中随机对象的方式。 - 你可以自己找出对象的类型并推断出相应的函数来调用:一个典型的方法是在基 class 中有一个输入字段并用它来向下转换用
static_cast
。但这不是最佳做法。添加您自己的类似 RTTI 的功能而不是使用编译器的优化功能不会比多态更有效。 - 您可以使用
std::variant
or astd::any
:这些提供了使用编译时功能提供某种 运行 时间相关行为的可能性(不一定要求从共同基础)。
剩下的问题是,如果需要,为什么要避免正常的多态性。