문제

나는 최근에 다음과 같은 상황에 갇혔습니다.

class A
{
public:
    typedef struct/class {...} B;
...
    C::D *someField;
}

class C
{
public:
    typedef struct/class {...} D;
...
    A::B *someField;
}

일반적으로 클래스 이름을 선언 할 수 있습니다.

class A;

그러나 중첩 유형을 선언 할 수는 없습니다. 다음은 컴파일 오류를 원인입니다.

class C::D;

어떤 아이디어?

도움이 되었습니까?

해결책

당신은 그것을 할 수 없습니다. 그것은 C ++ 언어의 구멍입니다. 중첩 된 클래스 중 하나 이상이 아닌 것입니다.

다른 팁

class IDontControl
{
    class Nested
    {
        Nested(int i);
    };
};

다음과 같은 전진 참조가 필요했습니다.

class IDontControl::Nested; // But this doesn't work.

내 해결 방법은 다음과 같습니다.

class IDontControl_Nested; // Forward reference to distinct name.

나중에 전체 정의를 사용할 수있을 때 :

#include <idontcontrol.h>

// I defined the forward ref like this:
class IDontControl_Nested : public IDontControl::Nested
{
    // Needed to make a forwarding constructor here
    IDontControl_Nested(int i) : Nested(i) { }
};

이 기술은 부드럽게 상속되지 않은 복잡한 생성자 나 다른 특수 회원 기능이있는 경우 가치가있는 것보다 더 어려울 것입니다. 특정 템플릿 마법이 심하게 반응하는 것을 상상할 수있었습니다.

그러나 매우 간단한 경우에는 효과가있는 것 같습니다.

헤더 파일의 불쾌한 헤더 파일을 #인치하는 것을 실제로 피하려면 다음을 수행 할 수 있습니다.

HPP 파일 :

class MyClass
{
public:
    template<typename ThrowAway>
    void doesStuff();
};

CPP 파일

#include "MyClass.hpp"
#include "Annoying-3rd-party.hpp"

template<> void MyClass::doesStuff<This::Is::An::Embedded::Type>()
{
    // ...
}

하지만:

  1. 호출 시간에 임베디드 유형을 지정해야합니다 (특히 기능이 포함 된 유형의 매개 변수를 사용하지 않는 경우)
  2. 기능은 가상이 될 수 없습니다 (템플릿이기 때문에)

그래, 트레이드 오프 ...

이것은 할 수 있습니다 앞으로 외부 클래스를 네임 스페이스로 선언하십시오.

샘플 : 우리는 중첩 된 클래스를 사용해야합니다.

기타 _a.h

namespace others {
struct A {
    struct Nested {
        Nested(int i) :i(i) {}
        int i{};
        void print() const { std::cout << i << std::endl; }
    };
};
}

my_class.h

#ifndef MY_CLASS_CPP
// A is actually a class
namespace others { namespace A { class Nested; } }
#endif

class MyClass {
public:
    MyClass(int i);
    ~MyClass();
    void print() const;
private:
    std::unique_ptr<others::A::Nested> _aNested;
};

my_class.cpp

#include "others_a.h"
#define MY_CLASS_CPP // Must before include my_class.h
#include "my_class.h"

MyClass::MyClass(int i) :
    _aNested(std::make_unique<others::A::Nested>(i)) {}
MyClass::~MyClass() {}
void MyClass::print() const {
    _aNested->print();
}

나는 이것을 답이라고 부르지 않지만 그럼에도 불구하고 흥미로운 발견입니다. C라는 네임 스페이스에서 구조물의 선언을 반복하면 모든 것이 정상입니다 (적어도 GCC에서). C의 클래스 정의가 발견되면 NamSpace C를 조용히 덮어 쓰는 것 같습니다.

namespace C {
    typedef struct {} D;
}

class A
{
public:
 typedef struct/class {...} B;
...
C::D *someField;
}

class C
{
public:
   typedef struct/class {...} D;
...
   A::B *someField;
}

이것은 해결 방법이 될 것입니다 (적어도 질문에 설명 된 문제는 실제 문제가 아니라, 즉 정의를 제어하지 않을 때 C):

class C_base {
public:
    class D { }; // definition of C::D
    // can also just be forward declared, if it needs members of A or A::B
};
class A {
public:
    class B { };
    C_base::D *someField; // need to call it C_base::D here
};
class C : public C_base { // inherits C_base::D
public:
    // Danger: Do not redeclare class D here!!
    // Depending on your compiler flags, you may not even get a warning
    // class D { };
    A::B *someField;
};

int main() {
    A a;
    C::D * test = a.someField; // here it can be called C::D
}

클래스 C와 D의 소스 코드를 변경하는 데 액세스 할 수있는 경우 클래스 D를 별도로 가져 와서 클래스 C에서 동의어를 입력 할 수 있습니다.

class CD {

};

class C {
public:

    using D = CD;

};

class CD;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top