简体   繁体   中英

C++ override function from same base template class with multiple inheritance ambiguous function call

I need to call init(int* iNumber) function which is derived from the base class.

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;
}

MainClass

#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;
}

At compile time this is gives the error

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

What am I doing wrong here? How could I fix it with minimal changes?

This code fails because C++ performs name lookup before overload resolution and access control check. That is first step would be to determine to which class scope init belongs to. And in this case result would be ambiguous because init could refer to either BaseClass<int>::init or BaseClass<float>::init . Introducing an extra using declaration will bring both of those functions into ChildClass scope:

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

So name lookup will determine that init refers to ChildClass::init and compiler will proceed to overload resolution.

Alternatively you can perform a cast (which is definitely not as convenient):

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM