Я пишу кроссплатформенную иерархию классов и хочу сохранить зависимые от платформы реализации в своем собственном классе (в отличие от наличия одного класса с #ifdefs
). Это то, что я до сих пор, но компилятор жалуется, что BaseDef
это личное. Любая помощь с тем, как я мог бы сохранить эту базовую структуру во время компиляции, будет принята с благодарностью 🙂
Редактировать: Казалось бы из Вот что это невозможно. Любой другой способ, которым я мог бы сохранить эту общую структуру и все еще компилировать?
Root.h
class Root {
private:
class BaseDef {
virtual void foo() = 0;
virtual void bar() = 0;
};
#ifdef _WIN32
class WinImp;
#else
class NixImp;
#endif
BaseDef* imp;
BaseDef* getImp();
public:
Root() : imp(getImp()) {}
void foo();
void bar();
};
Root.cpp
#include "Root.h"void Root::foo() {
imp->foo();
}
void Root::bar() {
imp->bar();
}
WinImp.h
#ifdef _WIN32
#include "Root.h"class WinImp : public Root::BaseDef {
public:
void foo();
void bar();
};
#endif
WinImp.cpp
#include "WinImp.h"#ifdef _WIN32
Root::WinImp::foo() {
}
Root::WinImp::bar() {
}
Root::BaseDef* Root::getImp() {
return new Root::WinImp();
}
#endif
Ваша главная проблема в том, что BaseDef
это личное. Это означает, что другие классы (кроме самого Root) не могут получить доступ к BaseDef
название. Один из способов сделать BaseDef
общественности. В качестве альтернативы вы можете сделать производные классы (WinImp
а также NixImp
) друзья Root
чтобы они могли получить доступ к BaseDef
название. К тому же Root
не может получить доступ к членам BaseDef
поэтому они должны быть публичными или сделать Root
друг BaseDef
,
class Root {
private:
class BaseDef {
public:
// These need to be public so that Root can see them or Root needs to be a friend.
//Nothing else can see BaseDef though so this is safe.
virtual void foo() = 0;
virtual void bar() = 0;
};
class WinImp; // Forward declare the classes
friend class WinImp; // And then make them friends
class NixImp;
friend class NixImp;
BaseDef* imp;
BaseDef* getImp();
public:
Root() : imp(getImp()) {}
void foo();
void bar();
};
void Root::foo() {
imp->foo();
}
void Root::bar() {
imp->bar();
}
// Since this is a nested class i made it Root::WinImp
class Root::WinImp : public Root::BaseDef {
public:
void foo();
void bar();
};
void Root::WinImp::foo() {}
void Root::WinImp::bar() {}
Root::BaseDef* Root::getImp() {
return new WinImp();
}
Этот метод не разрешен в соответствии со стандартом 2003 (11.4.p2), но в C ++ 11 (тот же пример) он явно разрешен (11.3.p2). Однако clang (протестированный 3.1) принимает это даже в режиме 2003. gcc (проверено 4.7.2) принимает это (даже в режиме 2003), если производные классы вложены в один и тот же класс, но не если он находится вне класса.
Жалуется что BaseDef
является private
…
class Root {
private:
class BaseDef {
virtual void foo() = 0;
virtual void bar() = 0;
};
Так что сделайте это публичным …
class Root {
public:
class BaseDef {
virtual void foo() = 0;
virtual void bar() = 0;
};
Сноска:
Вы пытаетесь избежать #ifdef
так что избавьтесь от этого:
#ifdef _WIN32
class WinImp;
#else
class NixImp;
#endif
Вместо этого просто используйте один класс:
class Imp;