【问题标题】:dereferencing void pointers to objects取消引用指向对象的 void 指针
【发布时间】:2021-07-19 18:51:06
【问题描述】:

将以下代码作为最低工作示例:

#include <iostream>

class Object_A
{
public:
    int attribute_a,attribute_b;
    
    Object_A(int a,int b){
        this->attribute_a = a;
        this->attribute_b = b; 
    }
    
    int object_method(){
        std::cout << "Hello from Object A: " << std::endl;
        return (this->a + this->b);
    }
    
};

class Object_B
{
public:
    int attribute_c, attribute_d;
    
    Object_B(int c,int d){
        this->attribute_c = c;
        this->attribute_d = d; 
    }
        
    int object_method(){
        std::cout << "Hello from Object B" << std::endl;
        return (this->c + this->d);
    }

};


class Object_Omega
{
public:
        
    Object_A alpha;
    Object_B beta;
    
    Object_Omega (Object_A first, Object_B second):
        alpha(first),
        beta(second)
    {}

    int foobar(int a){ return a; }
    
};

void according_to_user_input(bool input,Object_Omega obj)
{
    
    void * either_A_or_B;
    
    if (input){ either_A_or_B = & obj.alpha; }
    else      { either_A_or_B = & obj.beta;  }
    
                       /* problem here */
    for(int i = 0; i < either_A_or_B->object_method(); i++)
    {
        std::cout << i << std::endl;
    }

}

int main()
{   
    /* this happens somewhere */
    Object_A new_A = Object_A(1,2);
    Object_B new_B = Object_B(3,4);
    Object_Omega W = Object_Omega(new_A, new_B);

        
    according_to_user_input(true/*false*/, W);
    
    return 0;
}

我希望使用 void 指针(例如,在函数 according_to_user_input 内),但我很难理解正确的方法来做到这一点。 [1][2] 也有人问过类似的问题,但在指针指向的值是自定义对象的情况下,我没有设法完成这项工作。

鉴于用户输入,我希望从 A 或从 B 通过 Omega 对象调用 object_method()。不幸的是,我一直在处理的代码具有这种展示行为,而不是对象之间的继承关系,以避免丑陋的 void 类似 C 并且绝对不是类似 C++ 的场景。

提前谢谢你!

【问题讨论】:

  • 我不确定您的示例有多具有代表性,以及是否允许您使用 C++11,但通常我会使用从一个通用基类、智能指针(例如 std::shared_ptr)和 @ 继承987654333@ 函数可以完全避免这种情况。如有必要,您可以使用std::static_pointer_cast
  • 和我昨天给的答案here类似。

标签: c++ void-pointers


【解决方案1】:

您不能通过指向void 的指针进行间接寻址。并且不需要指向void 的指针。

最简单的解决办法是这样的:

int number = 1;
std::cout << input
    ? obj.alpha.object_method(number)
    : obj.beta.object_method(number);

对于已编辑的问题:上述方法仍然有效,但您可以使用函数模板摆脱复杂代码的重复。这是一个使用 lambda 的示例:

auto do_stuff = [](auto& either_A_or_B) {
    for(int i = 0; i < either_A_or_B.object_method(); i++)
    {
        std::cout << i << std::endl;
    }
};
input
    ? do_stuff(obj.alpha)
    : do_stuff(obj.beta);

附:避免使用 C 风格的强制转换。

【讨论】:

  • 如果可能的话,我会建议 OP 重写代码以改用多态性。
  • @2b-t 基于这个问题,OP 似乎已经意识到了这一点。说的Unfortunately the code that I've been working on has this showcased behavior as is and not as an inheritance relationship
  • 你好@eeronika。感谢您的回复。也许我没有正确解释。我将编辑帖子,以便更好地解释我想要做什么。的确,鉴于这个例子,我给出的问题可以通过用户输入的简单 if-then 案例来解决。
  • @eerorika 我更新了示例。希望它现在更有意义。
  • @ex1led 模板是一种生成类和函数的方式,除了作为模板参数提供的类型或编译时间值之外,这些类和函数在其他方面都是相同的。所以,如果你想为 A 类型的对象做 X 并且你想为不相关的 B 类型的对象做同样的 X,那么模板是一种方便的方法来生成 X(A) 和 X(B),而无需重复。这有时被称为“通用编程”。
【解决方案2】:

这不是void* 的好用处,如果像您评论的那样,您不能使用继承并且实际问题不仅仅是控制台输出,那么您仍然可以使用函数模板使其通用

template <class T>
void according_to_user_input(T &obj)
{
    std::cout << obj.object_method();
}

并像这样使用它

if (input)
    according_to_user_input<Object_A>(W.alpha);
else
    according_to_user_input<Object_B>(W.beta);

【讨论】:

  • 哦,模板。这可能是我需要的!我没有考虑过。我对这门语言没有那么丰富的经验,但我确实认为这也可以解决我所读到的问题。我会仔细看看的。谢谢。
猜你喜欢
  • 1970-01-01
  • 2012-03-25
  • 2011-10-20
  • 2015-01-04
  • 1970-01-01
  • 1970-01-01
  • 2021-07-22
  • 2011-06-17
  • 1970-01-01
相关资源
最近更新 更多