具有非共享方法的虚函数
Virtual function with non-shared method
我正在进行个人项目,我需要做一些不寻常的事情。我的代码有点长,但问题出在结构上,所以我将使用一个非常简化的问题版本。
- 我有两个 classes(A 和 B),B 派生自 A。
- B 使用 A 的所有属性和方法,包括创建修改后的
class.
实例的克隆
问题是我需要能够在克隆后使用B的方法(在本例中为moo),它在A中不存在。我试图使我的方法是虚拟的,但它不能解决问题。如果没有 CRTP,有什么办法可以做到这一点吗?
我真的不想使用 CRTP,因为它真的很复杂。
(在我的真实代码中,我有 4 个 class 继承链,所有 4 个都已经模板化了)
#include <iostream>
class A
{
public:
/*Common function*/
virtual void foo(){
std::cout << "call from A" << std::endl;
}
A* clone(){
/*
...
... Code I don't want to write again for B
...
*/
return this;
}
};
class B: public A
{
public:
/*Common function*/
virtual void foo(){
std::cout << "call from B" << std::endl;
}
/*Not derived from A*/
void moo(){ //Doesn't work even with virtual keyword
std::cout << "only exist in B" << std::endl;
}
};
int main(int argc, char const *argv[])
{
auto tB = new B();
tB->foo();
tB->moo();
tB->clone()->foo();
tB->clone()->moo();
return 0;
}
编译器:
error: 'class A' has no member named 'moo'; did you mean 'foo'?
38 | tB->clone()->moo();
| ^~~
| foo
我不是英语,如果不清楚,请见谅。
好吧,根据评论、我的研究以及我认为 c++ 的工作方式,我放弃了寻找看起来像虚方法但仍然令人满意的东西。
所以我决定使用 CRTP,对于那些感兴趣的人,这里是我的模型 3(我删除了一个)的代码继承了 class CRTP,带有一个额外的类型模板参数:)
#include <iostream>
//CRTPI = "CRTP Interface", used for inheritances between CRTPs
template<typename Derived, typename T>
class CRTPI_A
{
protected:
T x = 0;
public:
T getX(){
return x;
}
Derived* clone(){
/*
...
... Code I don't want to write again for B and it's childs
...
*/
return new Derived();
}
};
template<typename Derived, typename T>
class CRTPI_B: public CRTPI_A<Derived, T>
{
public:
//Only for B and its childs
void iwd(){
std::cout << "Hi, i'm a B child !" << std::endl;
}
};
template<typename Derived, typename T>
class CRTPI_C: public CRTPI_B<Derived, T>{};
template<typename T>
class A: public CRTPI_A<A<T>, T>
{
public:
A(){};
A(T z){
this->x = z;
}
void foo(){
std::cout << "call from A" << std::endl;
}
};
template<typename T>
class B: public CRTPI_B<B<T>, T>
{
public:
B(){};
B(T z){
this->x = z;
}
void foo(){
std::cout << "call from B" << std::endl;
}
//Not in CRTP interface so won't be inherited by C
void UwU(){
std::cout << "I'm exclusive to B" << std::endl;
}
};
template<typename T>
class C: public CRTPI_C<C<T>, T>
{
public:
C(){};
C(T z){
this->x = z;
};
void foo(){
std::cout << "call from C" << std::endl;
}
};
int main(int argc, char const *argv[])
{
auto tA = new A<char>('A');
auto tB = new B<int>(2);
auto tC = new C<float>(420.69);
tA->foo();
tA->clone()->foo();
printf("\n");
tB->foo();
tB->iwd();
tB->clone()->foo();
tB->clone()->iwd();
tB->UwU();
printf("\n");
tC->foo();
tC->iwd();
// tC->UwU(); //Won't work but that's planned
std::cout << "\n" << tA->getX() << ":" << tB->getX() <<":" << tC->getX() << std::endl;
return 0;
}
注意,这里 C 的 CRTP 接口是可选的,因为它没有子 class 也没有独占方法,所以我们可以只写:
template<typename T>
class C: CRTPI_B<C<T>, T>
{
...
}
我正在进行个人项目,我需要做一些不寻常的事情。我的代码有点长,但问题出在结构上,所以我将使用一个非常简化的问题版本。
- 我有两个 classes(A 和 B),B 派生自 A。
- B 使用 A 的所有属性和方法,包括创建修改后的 class. 实例的克隆
问题是我需要能够在克隆后使用B的方法(在本例中为moo),它在A中不存在。我试图使我的方法是虚拟的,但它不能解决问题。如果没有 CRTP,有什么办法可以做到这一点吗?
我真的不想使用 CRTP,因为它真的很复杂。 (在我的真实代码中,我有 4 个 class 继承链,所有 4 个都已经模板化了)
#include <iostream>
class A
{
public:
/*Common function*/
virtual void foo(){
std::cout << "call from A" << std::endl;
}
A* clone(){
/*
...
... Code I don't want to write again for B
...
*/
return this;
}
};
class B: public A
{
public:
/*Common function*/
virtual void foo(){
std::cout << "call from B" << std::endl;
}
/*Not derived from A*/
void moo(){ //Doesn't work even with virtual keyword
std::cout << "only exist in B" << std::endl;
}
};
int main(int argc, char const *argv[])
{
auto tB = new B();
tB->foo();
tB->moo();
tB->clone()->foo();
tB->clone()->moo();
return 0;
}
编译器:
error: 'class A' has no member named 'moo'; did you mean 'foo'?
38 | tB->clone()->moo();
| ^~~
| foo
我不是英语,如果不清楚,请见谅。
好吧,根据评论、我的研究以及我认为 c++ 的工作方式,我放弃了寻找看起来像虚方法但仍然令人满意的东西。
所以我决定使用 CRTP,对于那些感兴趣的人,这里是我的模型 3(我删除了一个)的代码继承了 class CRTP,带有一个额外的类型模板参数:)
#include <iostream>
//CRTPI = "CRTP Interface", used for inheritances between CRTPs
template<typename Derived, typename T>
class CRTPI_A
{
protected:
T x = 0;
public:
T getX(){
return x;
}
Derived* clone(){
/*
...
... Code I don't want to write again for B and it's childs
...
*/
return new Derived();
}
};
template<typename Derived, typename T>
class CRTPI_B: public CRTPI_A<Derived, T>
{
public:
//Only for B and its childs
void iwd(){
std::cout << "Hi, i'm a B child !" << std::endl;
}
};
template<typename Derived, typename T>
class CRTPI_C: public CRTPI_B<Derived, T>{};
template<typename T>
class A: public CRTPI_A<A<T>, T>
{
public:
A(){};
A(T z){
this->x = z;
}
void foo(){
std::cout << "call from A" << std::endl;
}
};
template<typename T>
class B: public CRTPI_B<B<T>, T>
{
public:
B(){};
B(T z){
this->x = z;
}
void foo(){
std::cout << "call from B" << std::endl;
}
//Not in CRTP interface so won't be inherited by C
void UwU(){
std::cout << "I'm exclusive to B" << std::endl;
}
};
template<typename T>
class C: public CRTPI_C<C<T>, T>
{
public:
C(){};
C(T z){
this->x = z;
};
void foo(){
std::cout << "call from C" << std::endl;
}
};
int main(int argc, char const *argv[])
{
auto tA = new A<char>('A');
auto tB = new B<int>(2);
auto tC = new C<float>(420.69);
tA->foo();
tA->clone()->foo();
printf("\n");
tB->foo();
tB->iwd();
tB->clone()->foo();
tB->clone()->iwd();
tB->UwU();
printf("\n");
tC->foo();
tC->iwd();
// tC->UwU(); //Won't work but that's planned
std::cout << "\n" << tA->getX() << ":" << tB->getX() <<":" << tC->getX() << std::endl;
return 0;
}
注意,这里 C 的 CRTP 接口是可选的,因为它没有子 class 也没有独占方法,所以我们可以只写:
template<typename T>
class C: CRTPI_B<C<T>, T>
{
...
}