函数参数的类型转换

问题描述 投票:0回答:4
class A{
};

class B{
public:
    B();
    B(const &A);
};

void foo(A &a){

}

int main(){
   B b;
   foo(b); //error: invalid initialization of reference of type ‘A&’ from expression of type ‘B’
   return 0;
}

在上面的代码中,我有一个编译错误

错误:从类型“B”的表达式中对类型“A&”的引用进行无效初始化

可以通过函数重载foo()来解决该错误。但是,您还有其他建议我如何解决这个问题吗?

函数 foo(A &a) 不使用参数“a”作为输入。参数“a”只是函数 foo(A &a) 的输出。

谢谢。

c++ reference initialization
4个回答
3
投票

有很多选择……如果不了解您的程序正在尝试什么,就很难知道该推荐什么。 我们对 A 和 B 之间逻辑关系的一点了解是:

  • 只有 B 的构造函数之一需要对 A 对象的非常量引用
  • foo() 旨在与 A 或 B 一起使用

这意味着指向 A 的指针可能保存在 B 中,但引出了一个问题: foo() 应该与所有 B 一起使用(如果在构造时没有提供,则可能使用默认构造的 A)还是仅与那些通过引用构造的指针一起使用到A?

设计选项包括:

  • 从 A 派生 B(但默认构造函数表明 B 可以存在而无需“绑定”到 A)
  • A& get_A()
    和/或
    const A& get_A() const
    成员添加到
    class B
    ,然后致电
    foo(b.get_A());
    • 使用
      operator A&()
      operator const A&() const
    • 隐式执行此操作
    • 如果 A 是可选的,您可能会更喜欢
      A* get_A()
      等人
  • template <class A_or_B> foo(A_or_B&)
    如果 A 和 B 为 foo 提供正确的成员/语义来工作
  • 重载 foo,为每种类型提供不同的实现

探索性代码:

#include <iostream>

struct A
{
    int n_;
};

void foo(A& a)
{
   a.n_++;
}


struct B
{
    // e.g. B() : p_a_(new A), owner_(true) { } ?
    //      ~B() { if (owner_) delete p_a_; }
    B(A& a) : p_a_(&a) { }

    operator A&() { return *p_a_; }

    A* p_a_;
};

int main()
{
    A a;
    a.n_ = 2;
    B b(a);
    foo(a);
    foo(b);
    std::cout << a.n_ << '\n';
}

0
投票

问题是您试图将对象 B 隐式转换为对象 A。考虑到这些是单独的类,编译器将无法执行此操作。虽然可以将对象 B 的指针或引用显式转换为对象 A 的 */& ,但这会使编译器感到困惑,并且是一个非常糟糕的主意。

就像你要求编译器将苹果转换为橙子一样,无法完成。如果 B 是 A 的子类,那么这是完全可能的。但是,如果这两个类没有任何共同点或很少有共同点,那么您就不能简单地将其作为解决方法。但是,如果它们这样做,并且您有多个相关的类,请创建一个基类(包含共享方法),并使所有这些类都从它派生。

再次强调,请不要做类似

(A*)(&b)
的事情,因为如果您不知道 foo() 的参数中实际获得的是什么类,这将导致运行时问题(再次强调,除非 B 派生自 A ).

当然,最好的做法是重载 Foo()。

编辑:你看,你可以在 B 的构造函数中从 A 转换为 B。但是你需要一个 A 并且有一个 B,所以需要 REVERSE 转换。这就是为什么您当前的代码无法工作。


0
投票

你真的希望 A 和 B 是不相关的类吗?如果 A 类和 B 类共享 is-a 关系,那么最好从 A 派生 B。

class B : public A

然后

foo(b)
以 foo(A& a) 作为签名也会导致对象切片。


0
投票

最简单的方法..如果你愿意将对象B分配给对象A。你需要看看它们是否兼容。

要从我的角度进行编译,请尝试以下操作:

class A{ 

}; 

class B: public A{ 
public: 
    B(){
    }
    B(const A&){
    }
}; 

void foo(A &a){ 

}

希望它值得。

© www.soinside.com 2019 - 2024. All rights reserved.