没有类型转换的模板派生 class 的 C++ 访问成员
C++ access member of templated derived class without typecast
是否可以使用指向基 class 的指针访问派生 class 的成员?
// Example program
#include <iostream>
#include <vector>
#include <memory>
#include <string>
class A {
public:
std::string x = "this is the wrong x\n";
};
template <class T>
class B : public A {
public:
T x;
};
int main()
{
std::vector<std::unique_ptr<A>> vector;
auto i = std::make_unique<B<int>>();
i->x = 6;
vector.push_back(std::move(i));
for(auto &element : vector){
std::cout << element->x;
}
}
这里我总是得到classA的输出。我无法对其进行类型转换,因为我事先不知道该元素是类型A还是类型B。有没有正确的方法来做到这一点?
正确的方法是创建一个 virtual
函数来执行打印等任务。
class A {
public:
std::string x = "this is the wrong x\n";
virtual ~A() = default;
virtual void print() const { std::cout << x; }
};
template <class T>
class B : public A {
public:
T x;
virtual void print() const override { std::cout << x; }
};
int main()
{
std::vector<std::unique_ptr<A>> vector;
auto i = std::make_unique<B<int>>();
i->x = 6;
vector.push_back(std::move(i));
for(auto &element : vector){
element->print();
}
}
如果您有一个指向基 class 的指针,您只能访问在该基 class 上定义的内容(无需类型转换)。对于所有编译器所知,它 是 基类 class 的一个实例并且 没有 其他任何东西。
多态行为涉及使用 virtual
函数 - 派生的 classes 可以在调用基础 class 的 virtual
函数时更改调用哪个函数。请注意,成员不存在此机制(您会更改成员的哪些内容?只有类型,在派生的 class 中更改它毫无意义)。因此,您可以使用指向应该具有自定义行为的基 classes 的指针做的唯一有意义的事情是调用它们的虚函数。
现在,您可能会想到"ok, I'll just make access to x
go through a virtual function",但这里的问题是您已经在基class 中声明虚函数时必须指定涉及的类型。这是有道理的:编译器需要知道函数涉及哪些类型,即使是虚拟函数。您只能在重写函数中传递和 return 不同的类型,如果它们是 "compatible" - 请参阅 covariance and contravariance 了解更多信息。
所以除非你所有的 T
都是协变的,否则虚函数也帮不了你。
您的概念的核心缺陷是您希望非模板函数中的某些类型(即 element->x
)取决于某些对象的动态类型(即 element
)。这是不可能的,因为编译器必须在编译时知道每个表达式的类型。所以你必须以不同的方式处理你的问题。
是否可以使用指向基 class 的指针访问派生 class 的成员?
// Example program
#include <iostream>
#include <vector>
#include <memory>
#include <string>
class A {
public:
std::string x = "this is the wrong x\n";
};
template <class T>
class B : public A {
public:
T x;
};
int main()
{
std::vector<std::unique_ptr<A>> vector;
auto i = std::make_unique<B<int>>();
i->x = 6;
vector.push_back(std::move(i));
for(auto &element : vector){
std::cout << element->x;
}
}
这里我总是得到classA的输出。我无法对其进行类型转换,因为我事先不知道该元素是类型A还是类型B。有没有正确的方法来做到这一点?
正确的方法是创建一个 virtual
函数来执行打印等任务。
class A {
public:
std::string x = "this is the wrong x\n";
virtual ~A() = default;
virtual void print() const { std::cout << x; }
};
template <class T>
class B : public A {
public:
T x;
virtual void print() const override { std::cout << x; }
};
int main()
{
std::vector<std::unique_ptr<A>> vector;
auto i = std::make_unique<B<int>>();
i->x = 6;
vector.push_back(std::move(i));
for(auto &element : vector){
element->print();
}
}
如果您有一个指向基 class 的指针,您只能访问在该基 class 上定义的内容(无需类型转换)。对于所有编译器所知,它 是 基类 class 的一个实例并且 没有 其他任何东西。
多态行为涉及使用 virtual
函数 - 派生的 classes 可以在调用基础 class 的 virtual
函数时更改调用哪个函数。请注意,成员不存在此机制(您会更改成员的哪些内容?只有类型,在派生的 class 中更改它毫无意义)。因此,您可以使用指向应该具有自定义行为的基 classes 的指针做的唯一有意义的事情是调用它们的虚函数。
现在,您可能会想到"ok, I'll just make access to x
go through a virtual function",但这里的问题是您已经在基class 中声明虚函数时必须指定涉及的类型。这是有道理的:编译器需要知道函数涉及哪些类型,即使是虚拟函数。您只能在重写函数中传递和 return 不同的类型,如果它们是 "compatible" - 请参阅 covariance and contravariance 了解更多信息。
所以除非你所有的 T
都是协变的,否则虚函数也帮不了你。
您的概念的核心缺陷是您希望非模板函数中的某些类型(即 element->x
)取决于某些对象的动态类型(即 element
)。这是不可能的,因为编译器必须在编译时知道每个表达式的类型。所以你必须以不同的方式处理你的问题。