无法从继承的 class 模板中找到重载方法
can't find overloaded method from inherited class template
这是我第一次使用 class 模板,所以如果我犯了一个简单的错误,请不要太苛刻。
我有一个 class 模板 class A<class T>
。它有一个纯虚拟的方法 init()
,因此将在每个派生的 class 中单独实现。所有这些可能派生的 classes 的共同点是一个 init(T* i_x)
,它基本上做一些一般的事情然后调用 init()
。因为这对于每个派生的 class 都是相同的,所以我想在基础 class 模板中定义它。但不知何故,我的编译器找不到正确的函数。
如果我尝试在派生的对象上使用 init(T* i_x)
class A_der
我得到错误:
no matching function for call to 'A_der::init(B_der*)
用于模板参数 T
的 classes 将全部派生自另一个 class B
。因此,错误消息涉及从 class B
.
派生的 class B_der
我把问题归结为一个小例子,它应该包含对问题重要的所有内容。如果我尝试在 Visual Studio 中编译此示例(通常我在 STM32CubeIDE 中工作),我会收到以下错误
Severity Code Description Project File Line Suppression State
Error C2660 'A_der::init': function does not take 1
arguments template_class-overload_inherited_method [...]\main.cpp 8
所以编译器此时找到的唯一函数是 init()
而不是基础 class 模板方法 init(T* )
.
有人能告诉我为什么会这样吗?我该怎么做才能得到我想要的行为(无需在 A 的每个派生 class 中实现类似的 init(T* )
?
这是我的示例代码:
base class 模板 A - 声明 - A.hpp
template<class T>
class A
{
protected:
T* m_x;
public:
virtual void connect(T* i_x) final;
virtual void init() = 0;
virtual void init(T* i_x) final;
};
base class 模板 A - 实施 - A.cpp
#include "A.hpp"
template<class T>
void A<T>::connect(T* i_x)
{
//some checks
m_x = i_x; //connects object of B to A
}
template<class T>
void A<T>::init(T* i_x)
{
connect(i_x);
init();
}
派生classA_der
#include "A.hpp"
#include "B_der.hpp"
#pragma once
class A_der : public A<B_der>
{
void init() override;
};
void A_der::init()
{
//Initialization which needs a B_der connected already
}
main.cpp
#include "B_der.hpp"
#include "A_der.hpp"
int main(void)
{
B_der testB;
A_der testA;
testA.init(&testB);
return 0;
}
为了完整起见:
class B
{
};
class B_der : public B
{
};
编辑 - 已解决
非常感谢您的快速回复。
@BoP 和@Jarod42 的评论组合解决了这个问题。
我不得不用 using A<B_der>::init
取消隐藏方法(实际上重命名可能是更优雅的方式)并将 A
的实现移动到 A.hpp
.
我将在这里为我提供使用 Visual Studio 2019 成功构建的更新示例:
基础classA
template<class T>
class A
{
protected:
T* m_x;
public:
virtual void connect(T* i_x) final;
virtual void init() = 0;
virtual void init(T* i_x) final;
};
template<class T>
void A<T>::connect(T* i_x)
{
//some checks
m_x = i_x; //connects object of B to A
}
template<class T>
void A<T>::init(T* i_x)
{
connect(i_x);
init();
}
推导classA_der
A_der.hpp
#include "A.hpp"
#include "B_der.hpp"
class A_der : public A<B_der>
{
public:
void init() override;
using A<B_der>::init;
};
A_der.cpp
#include "A_der.hpp"
void A_der::init()
{
//Initialization which needs a B_der connected already
}
main.cpp
#include "B_der.hpp"
#include "A_der.hpp"
int main(void)
{
B_der testB;
A_der testA;
testA.init(&testB);
return 0;
}
完整性
B.hpp
class B
{
};
B_der.hpp
#include "B.hpp"
class B_der : public B
{
};
前面的例子中A_der
public的方法我也忘记了,这里更正一下。我在这个例子中删除了 #pragma once
s。
class A_der : public A<B_der>
{
void init() override;
};
当您在派生 class 中声明一个函数 init
时,它会隐藏基 class 中所有名为 init
的东西。这就像在内部作用域中声明某些东西一样——它从外部作用域中隐藏同名的东西。
有多种方法可以导入隐藏名称,但一个简单的解决方案是选择一个不同的名称,例如 init_base
。或者,可能更好,将参数传递给 class 构造函数。
这是我第一次使用 class 模板,所以如果我犯了一个简单的错误,请不要太苛刻。
我有一个 class 模板 class A<class T>
。它有一个纯虚拟的方法 init()
,因此将在每个派生的 class 中单独实现。所有这些可能派生的 classes 的共同点是一个 init(T* i_x)
,它基本上做一些一般的事情然后调用 init()
。因为这对于每个派生的 class 都是相同的,所以我想在基础 class 模板中定义它。但不知何故,我的编译器找不到正确的函数。
如果我尝试在派生的对象上使用 init(T* i_x)
class A_der
我得到错误:
no matching function for call to 'A_der::init(B_der*)
用于模板参数 T
的 classes 将全部派生自另一个 class B
。因此,错误消息涉及从 class B
.
class B_der
我把问题归结为一个小例子,它应该包含对问题重要的所有内容。如果我尝试在 Visual Studio 中编译此示例(通常我在 STM32CubeIDE 中工作),我会收到以下错误
Severity Code Description Project File Line Suppression State Error C2660 'A_der::init': function does not take 1 arguments template_class-overload_inherited_method [...]\main.cpp 8
所以编译器此时找到的唯一函数是 init()
而不是基础 class 模板方法 init(T* )
.
有人能告诉我为什么会这样吗?我该怎么做才能得到我想要的行为(无需在 A 的每个派生 class 中实现类似的 init(T* )
?
这是我的示例代码:
base class 模板 A - 声明 - A.hpp
template<class T>
class A
{
protected:
T* m_x;
public:
virtual void connect(T* i_x) final;
virtual void init() = 0;
virtual void init(T* i_x) final;
};
base class 模板 A - 实施 - A.cpp
#include "A.hpp"
template<class T>
void A<T>::connect(T* i_x)
{
//some checks
m_x = i_x; //connects object of B to A
}
template<class T>
void A<T>::init(T* i_x)
{
connect(i_x);
init();
}
派生classA_der
#include "A.hpp"
#include "B_der.hpp"
#pragma once
class A_der : public A<B_der>
{
void init() override;
};
void A_der::init()
{
//Initialization which needs a B_der connected already
}
main.cpp
#include "B_der.hpp"
#include "A_der.hpp"
int main(void)
{
B_der testB;
A_der testA;
testA.init(&testB);
return 0;
}
为了完整起见:
class B
{
};
class B_der : public B
{
};
编辑 - 已解决
非常感谢您的快速回复。
@BoP 和@Jarod42 的评论组合解决了这个问题。
我不得不用 using A<B_der>::init
取消隐藏方法(实际上重命名可能是更优雅的方式)并将 A
的实现移动到 A.hpp
.
我将在这里为我提供使用 Visual Studio 2019 成功构建的更新示例:
基础classA
template<class T>
class A
{
protected:
T* m_x;
public:
virtual void connect(T* i_x) final;
virtual void init() = 0;
virtual void init(T* i_x) final;
};
template<class T>
void A<T>::connect(T* i_x)
{
//some checks
m_x = i_x; //connects object of B to A
}
template<class T>
void A<T>::init(T* i_x)
{
connect(i_x);
init();
}
推导classA_der
A_der.hpp
#include "A.hpp"
#include "B_der.hpp"
class A_der : public A<B_der>
{
public:
void init() override;
using A<B_der>::init;
};
A_der.cpp
#include "A_der.hpp"
void A_der::init()
{
//Initialization which needs a B_der connected already
}
main.cpp
#include "B_der.hpp"
#include "A_der.hpp"
int main(void)
{
B_der testB;
A_der testA;
testA.init(&testB);
return 0;
}
完整性
B.hpp
class B
{
};
B_der.hpp
#include "B.hpp"
class B_der : public B
{
};
前面的例子中A_der
public的方法我也忘记了,这里更正一下。我在这个例子中删除了 #pragma once
s。
class A_der : public A<B_der>
{
void init() override;
};
当您在派生 class 中声明一个函数 init
时,它会隐藏基 class 中所有名为 init
的东西。这就像在内部作用域中声明某些东西一样——它从外部作用域中隐藏同名的东西。
有多种方法可以导入隐藏名称,但一个简单的解决方案是选择一个不同的名称,例如 init_base
。或者,可能更好,将参数传递给 class 构造函数。