如何包含虚拟方法的文件?

时间:2016-07-12 23:41:46

标签: c++ include virtual

我有两个类层次结构:A s和B s。 A的虚方法返回BB的虚方法返回A

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 A1 : public A;

它应该有用。但是C ++不支持这样的类前向声明​​。如何解决?

1 个答案:

答案 0 :(得分:1)

在处理循环引用时,请在适当的地方使用前向声明而不是#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...
}

话虽这么说,前面声明结构是处理循环引用的唯一方法。但由于您无法转发声明层次结构,因此我认为如果不重新考虑您的设计,您的问题就无法解决。如果这不是一个选项,您将不得不停止使用协变返回值。

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()时,无论您在哪里依赖协方差,都必须使用类型转换。