【问题标题】:C++ override function from same base template class with multiple inheritance ambiguous function callC ++从具有多重继承模糊函数调用的同一基本模板类中覆盖函数
【发布时间】:2017-12-12 10:17:48
【问题描述】:

我需要调用派生自基类的init(int* iNumber) 函数。

BaseClass.h

#pragma once
#include "stdafx.h"
template <class T>
class BaseClass
{
public:
    BaseClass() {}
    virtual ~BaseClass() {}
    virtual void init(T* object) = 0;
};

ChildClass.h

#pragma once
#include "BaseClass.h"

class ChildClass : public BaseClass<int>, public BaseClass<float>
{
public:
    ChildClass() {}
    virtual ~ChildClass() {}
};

ChildClassImpl.h

#pragma once
#include "ChildClass.h"
class ChildClassImpl : public ChildClass
{
public:
    ChildClassImpl();
    virtual ~ChildClassImpl();
private:
    void init(int* iNumber) override;
    void init(float* fNumber) override;
};

ChildClassImpl.cpp

#include "stdafx.h"
#include <iostream>
#include "ChildClassImpl.h"

ChildClassImpl::ChildClassImpl(){}

ChildClassImpl::~ChildClassImpl(){}

void ChildClassImpl::init(int* iNumber)
{
    std::cout << "Integer constructor: " << *iNumber << std::endl;
}

void ChildClassImpl::init(float* fNumber)
{
    std::cout << "Float constructor: " << *fNumber << std::endl;
}

主类

#include "stdafx.h"
#include <iostream>
#include "ChildClassImpl.h"

using namespace std;

int main()
{
    ChildClass* childClass = new ChildClassImpl();
    int x = 10;
    childClass->init(&x);
    cout << "Test" << endl;
    getchar();
    return 0;
}

在编译时会报错

Severity  Code    Description Project File    Line Error
(active)      "BaseClass<T>::init [with T=int]" is
ambiguous ConsoleApplication4 d:\Learning\ConsoleApplication4\ConsoleApplication4\ConsoleApplication4.cpp 14

我在这里做错了什么?我怎样才能通过最小的更改来修复它?

【问题讨论】:

  • using BaseClass&lt;int&gt;::init;using BaseClass&lt;float&gt;::init; 放在ChildClass 的声明中
  • 您从ChildClassImpl::init 函数编写的输出告诉我您不应该拥有这些函数。相反,它们的功能应该放在 actual 构造函数中。
  • @SPD:公平地说,这是一个说明问题的小例子,而不是一个好的程序设计的广告。
  • 谢谢@PiotrSkotnicki。它确实奏效了。如果您能解释为什么会发生这种情况,那就更好了。为什么编译器无法找出正确的基类?
  • 预模板 C++ 的解析规则基本上说基础方法仅在名称上自动提升/冲突,并且不考虑参数,这是一个弱点。好处是这允许派生类使用另一个签名来屏蔽这两种方法。使用using 手动提升这两种方法可以启动适当的重载解决方案,但如果您有许多具有此行为的方法,则无济于事。您的示例显示了我喜欢的模板用法,但不适合以前的语言,当时必须显式命名两个基类。

标签: c++ c++11 multiple-inheritance ambiguous name-lookup


【解决方案1】:

此代码失败,因为 C++ 在重载解析和访问控制检查之前执行名称查找。第一步是确定init 属于哪个类范围。在这种情况下,结果将是模棱两可的,因为init 可以指代BaseClass&lt;int&gt;::initBaseClass&lt;float&gt;::init。引入额外的using 声明会将这两个函数都带入ChildClass 范围:

class ChildClass : public BaseClass<int>, public BaseClass<float>
{
public: using BaseClass<int>::init;
public: using BaseClass<float>::init;

因此名称查找将确定init 引用ChildClass::init,编译器将继续进行重载决策。

您也可以进行强制转换(这绝对不是那么方便):

static_cast<BaseClass<int> *>(childClass)->init(&x);

【讨论】:

  • 感谢@VTT 的解决方案和解释。
猜你喜欢
  • 1970-01-01
  • 2010-12-26
  • 1970-01-01
  • 1970-01-01
  • 2021-12-20
  • 2021-04-20
  • 1970-01-01
  • 2017-06-28
  • 2019-08-05
相关资源
最近更新 更多