如何包含虚拟方法的文件?
How to include files for virtual methods?
我有两个 class 层次结构:A
和 B
。 A
s 有虚方法 return B
s,B
s 有虚方法 return A
s.
A.h
#pragma once
class B;
struct A
{
virtual B* f() = 0;
};
A1.h
#pragma once
#include "A.h"
#include "B1.h"
struct A1 : public A
{
B1* f() override;
};
B.h
#pragma once
class A;
struct B
{
virtual A* g() = 0;
};
B1.h
#pragma once
#include "B.h"
#include "A1.h"
struct B1 : public B
{
A1* g() override;
};
在 VS2015 中没有编译错误
overriding virtual function return type differs and is not covariant from A
带有class前向声明
class A1 : public A;
应该可以。但是 C++ 不支持这种 class 前向声明。如何解决?
处理循环引用时,在适当的地方使用前向声明而不是 #include
语句。
此外,头文件本身应该有保护措施,以避免在多次 #include
时多次声明其内容。守卫本身可以使用 #ifndef
/#define
对,或 #pragma once
,具体取决于您的编译器。
A.h
#ifndef A_H
#define A_H
struct B;
struct A
{
virtual B* f() = 0;
};
#endif
或:
#pragma once
struct B;
struct A
{
virtual B* f() = 0;
};
A1.h:
#ifndef A1_H
#define A1_H
#include "A.h"
struct B1;
struct A1 : public A
{
B1* f() override;
};
#endif
或:
#pragma once
#include "A.h"
struct B1;
struct A1 : public A
{
B1* f() override;
};
A2.h
#ifndef A2_H
#define A2_H
#include "A.h"
struct B2;
struct A2 : public A
{
B2* f() override;
};
#endif
或:
#pragma once
#include "A.h"
struct B2;
struct A2 : public A
{
B2* f() override;
};
B.h
#ifndef B_H
#define B_H
struct A;
struct B
{
virtual A* g() = 0;
};
#endif
或:
#pragma once
struct A;
struct B
{
virtual A* g() = 0;
};
B1.h
#ifndef B1_H
#define B1_H
#include "B.h"
struct A1;
struct B1 : public B
{
A1* g() override;
};
#endif
或:
#pragma once
#include "B.h"
struct A1;
struct B1 : public B
{
A1* g() override;
};
B2.h
#ifndef B2_H
#define B2_H
#include "B.h"
struct A2;
struct B2
{
A2* g() override;
};
#endif
或
#pragma once
#include "B.h"
struct A2;
struct B2
{
A2* g() override;
};
满足前向声明类的#include
语句应该在方法实现源文件中使用,而不是在它们声明的头文件中使用:
A1.cpp:
#include "A1.h"
#include "B1.h" // <--
B1* A1::f()
{
return new B1; // or wherever the B1 object comes from...
}
A2.h
#include "A2.h"
#include "B2.h" // <--
B2* A2::f()
{
return new B2; // or wherever the B2 object comes from...
}
B1.cpp
#include "B1.h"
#include "A1.h" // <--
A1* B1::g()
{
return new A1; // or wherever the A1 object comes from...
}
B2.cpp
#include "B2.h"
#include "A2.h" // <--
A2* B2::g()
{
return new A2; // or wherever the A2 object comes from...
}
也就是说,向前声明结构是处理循环引用的唯一方法。但是由于您不能转发声明层次结构,所以我认为如果不重新考虑您的设计就无法解决您的问题。如果这不是一个选项,您将不得不远离使用协变 return 值。
A.h
#pragma once
struct B;
struct A
{
virtual B* f() = 0;
};
A1.h:
#pragma once
#include "A.h"
struct A1 : public A
{
B* f() override;
};
A2.h
#pragma once
#include "A.h"
struct A2 : public A
{
B* f() override;
};
B.h
#pragma once
struct A;
struct B
{
virtual A* g() = 0;
};
B1.h
#pragma once
#include "B.h"
struct B1 : public B
{
A* g() override;
};
B2.h
#pragma once
#include "B.h"
struct B2
{
A* g() override;
};
A1.cpp:
#include "A1.h"
#include "B1.h" // <--
B* A1::f()
{
return new B1; // or wherever the B1 object comes from...
}
A2.h
#include "A2.h"
#include "B2.h" // <--
B* A2::f()
{
return new B2; // or wherever the B2 object comes from...
}
B1.cpp
#include "B1.h"
#include "A1.h" // <--
A* B1::g()
{
return new A1; // or wherever the A1 object comes from...
}
B2.cpp
#include "B2.h"
#include "A2.h" // <--
A* B2::g()
{
return new A2; // or wherever the A2 object comes from...
}
这只是意味着在调用 f()
和 g()
.
时,无论在何处依赖协方差,都必须使用类型转换
我有两个 class 层次结构:A
和 B
。 A
s 有虚方法 return B
s,B
s 有虚方法 return A
s.
A.h
#pragma once
class B;
struct A
{
virtual B* f() = 0;
};
A1.h
#pragma once
#include "A.h"
#include "B1.h"
struct A1 : public A
{
B1* f() override;
};
B.h
#pragma once
class A;
struct B
{
virtual A* g() = 0;
};
B1.h
#pragma once
#include "B.h"
#include "A1.h"
struct B1 : public B
{
A1* g() override;
};
在 VS2015 中没有编译错误
overriding virtual function return type differs and is not covariant from A
带有class前向声明
class A1 : public A;
应该可以。但是 C++ 不支持这种 class 前向声明。如何解决?
处理循环引用时,在适当的地方使用前向声明而不是 #include
语句。
此外,头文件本身应该有保护措施,以避免在多次 #include
时多次声明其内容。守卫本身可以使用 #ifndef
/#define
对,或 #pragma once
,具体取决于您的编译器。
A.h
#ifndef A_H
#define A_H
struct B;
struct A
{
virtual B* f() = 0;
};
#endif
或:
#pragma once
struct B;
struct A
{
virtual B* f() = 0;
};
A1.h:
#ifndef A1_H
#define A1_H
#include "A.h"
struct B1;
struct A1 : public A
{
B1* f() override;
};
#endif
或:
#pragma once
#include "A.h"
struct B1;
struct A1 : public A
{
B1* f() override;
};
A2.h
#ifndef A2_H
#define A2_H
#include "A.h"
struct B2;
struct A2 : public A
{
B2* f() override;
};
#endif
或:
#pragma once
#include "A.h"
struct B2;
struct A2 : public A
{
B2* f() override;
};
B.h
#ifndef B_H
#define B_H
struct A;
struct B
{
virtual A* g() = 0;
};
#endif
或:
#pragma once
struct A;
struct B
{
virtual A* g() = 0;
};
B1.h
#ifndef B1_H
#define B1_H
#include "B.h"
struct A1;
struct B1 : public B
{
A1* g() override;
};
#endif
或:
#pragma once
#include "B.h"
struct A1;
struct B1 : public B
{
A1* g() override;
};
B2.h
#ifndef B2_H
#define B2_H
#include "B.h"
struct A2;
struct B2
{
A2* g() override;
};
#endif
或
#pragma once
#include "B.h"
struct A2;
struct B2
{
A2* g() override;
};
满足前向声明类的#include
语句应该在方法实现源文件中使用,而不是在它们声明的头文件中使用:
A1.cpp:
#include "A1.h"
#include "B1.h" // <--
B1* A1::f()
{
return new B1; // or wherever the B1 object comes from...
}
A2.h
#include "A2.h"
#include "B2.h" // <--
B2* A2::f()
{
return new B2; // or wherever the B2 object comes from...
}
B1.cpp
#include "B1.h"
#include "A1.h" // <--
A1* B1::g()
{
return new A1; // or wherever the A1 object comes from...
}
B2.cpp
#include "B2.h"
#include "A2.h" // <--
A2* B2::g()
{
return new A2; // or wherever the A2 object comes from...
}
也就是说,向前声明结构是处理循环引用的唯一方法。但是由于您不能转发声明层次结构,所以我认为如果不重新考虑您的设计就无法解决您的问题。如果这不是一个选项,您将不得不远离使用协变 return 值。
A.h
#pragma once
struct B;
struct A
{
virtual B* f() = 0;
};
A1.h:
#pragma once
#include "A.h"
struct A1 : public A
{
B* f() override;
};
A2.h
#pragma once
#include "A.h"
struct A2 : public A
{
B* f() override;
};
B.h
#pragma once
struct A;
struct B
{
virtual A* g() = 0;
};
B1.h
#pragma once
#include "B.h"
struct B1 : public B
{
A* g() override;
};
B2.h
#pragma once
#include "B.h"
struct B2
{
A* g() override;
};
A1.cpp:
#include "A1.h"
#include "B1.h" // <--
B* A1::f()
{
return new B1; // or wherever the B1 object comes from...
}
A2.h
#include "A2.h"
#include "B2.h" // <--
B* A2::f()
{
return new B2; // or wherever the B2 object comes from...
}
B1.cpp
#include "B1.h"
#include "A1.h" // <--
A* B1::g()
{
return new A1; // or wherever the A1 object comes from...
}
B2.cpp
#include "B2.h"
#include "A2.h" // <--
A* B2::g()
{
return new A2; // or wherever the A2 object comes from...
}
这只是意味着在调用 f()
和 g()
.