使用作为模板形参提供的基类成员,不带限定符
Use members of a base class provided as a template parameter without qualifiers
代码正常运行:
struct Defs
{
static const int a = 1;
int b{};
void g() {}
};
struct Bob : Defs
{
void f()
{
cout << a << "n";
cout << b << "n";
g();
}
};
int main()
{
Bob b;
b.f();
}
但是这段代码没有:
struct Defs
{
static const int a = 1;
int b{};
void g() {}
};
template<class D>
struct Bob : D
{
void f()
{
cout << a << "n";
cout << b << "n";
g();
}
};
int main()
{
Bob<Defs> b;
b.f();
}
错误:
prog.cpp: In member function 'void Bob<D>::f()':
prog.cpp:16:11: error: 'a' was not declared in this scope
cout << a << "n";
^
prog.cpp:17:11: error: 'b' was not declared in this scope
cout << b << "n";
^
prog.cpp:18:5: error: there are no arguments to 'g' that depend on a template parameter, so a declaration of 'g' must be available [-fpermissive]
g();
^
prog.cpp:18:5: note: (if you use '-fpermissive', G++ will accept your code, but allowing the use of an undeclared name is deprecated)
但是如果我做以下操作,它就可以工作了:
template<class D>
struct Bob : D
{
void f()
{
cout << D::a << "n";
cout << D::b << "n";
D::g();
}
};
是否有可能让一个类使用作为模板形参提供的基类的成员,而不限定它们?我问这个问题的原因是,这样做可以让我重构一些代码,而不需要做很多改变。
可以假设用作模板形参的类型具有所有这些成员,否则可以接受编译失败。
简介
出现错误是因为基类依赖于模板参数,这并不奇怪,因为基类直接使用模板参数。
错误诊断来自于这样一个事实:不同的模板参数可能在类内部产生明显不同的行为;如果传入的模板参数没有特定的成员怎么办?然后我们要在全局范围内查找一些东西吗?
- 在哪里,为什么我必须把"模板"answers"typename"关键字?
显式声明想要访问this
的成员
你是说你想访问基类的成员而不限定它们,如果我从字面上理解你的话,我会说你可以使用this->member-name
—但考虑到你写的关于重构的内容,我怀疑这是不是你想要的。
struct A {
int m;
};
template<class T>
struct B : T {
void func () {
this->m = 1;
}
};
int main () {
B<A> {}.func ();
}
从依赖的基类
引入名称另一种选择是显式声明您希望基类中的某些名称在派生它的基类中直接可用—使用using
,如下所示:
template<class T>
struct B : T {
using T::m;
void func () {
m = 1;
}
};
可以读作;"亲爱的编译器,无论我指的是m
,我希望你使用T
中的一个"。
但是我想破解这个问题;怎样! ?
引入一个非依赖基并让它引入引用到你真正想要的数据。如果您知道每个T
的名称,那么这将有效。
你甚至可以扩展这个hack,让它自动推断出那些成员的类型,但这与问题的范围相去甚远。
#include <iostream>
struct A {
int n;
int m;
void print () {
std::cout << m << std::endl;
}
};
struct Hack {
template<class T>
Hack (T* hck) : m (hck->m), n (hck->n) { }
int& m;
int& n;
};
template<class T>
struct B : T, Hack {
B () : Hack (static_cast<T*> (this)) { }
void func () {
m = 123;
}
};
int main () {
B<A> b;
b.func ();
b.print ();
}
你可以在这里找到一个运行的例子。警告的话;我个人是不会这么做的,但正如你所看到的,你可以通过一些间接的方式来完成你的要求。
您可以添加:
using D::a;
using D::b;
using D::g;
到Bob
修复你的作用域问题。
下面是对这个问题的全面概述。老实说,这是c++中不应该存在的一个角落,但是,没有语言是完美的=P
相关文章:
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何使用基类指针引用派生类成员
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 如果基类包含双指针成员,则派生类的构造函数
- 继承和友元函数,从基类访问受保护的成员
- 如何基于模板化类的基类专门化成员函数
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 在派生类中使用基类的私有成员变量的最佳方法
- 为什么我需要在成员发起器列表中重复基类的模板参数?
- 继承:调用基类的成员和方法
- 相同的层次结构,访问基类的受保护成员时的行为不同
- 当空基类也是成员变量时,为什么禁止空基优化?
- 引用基类模板的成员变量的简单方法
- 将基类的成员函数重载到其他派生类C++
- C++ 使用派生类方法更改基类数据成员
- 在成员构造函数之后调用基类构造函数
- 派生类看不到基类成员
- 使用派生类中的静态成员而不是基类
- 指向成员的 C++ 指针(指向成员基类的指针)
- 如何在c++中将模板成员函数的实参转发给成员基类指针