派生自在私有范围内声明的 class
Derive from class declared in private scope
我目前正在重构一些遗留代码,并希望将多个 if...elseif... 语句分解为一系列 classes 实现各种策略。
因为我必须访问原始对象的内部结构,所以我将把新的 classes 声明为嵌套的 classes;因为外部世界没有人可以访问它们,所以我更愿意在私有范围内声明它们。
为了尽可能少地暴露实现细节,我想知道是否可以在头文件中仅前向声明基本策略class,并将所有子class es 声明在实现文件中。代码示例如下:
-- 头文件
class MyUglyClass
{
private:
class IStrategyBase;
IStrategyBase* sPtr;
// class ActualImplementation; // this is what I'd like to avoid
// class YetAnotherImplementation; // as above
// blah blah blah
};
-- 实现文件
class MyUglyClass::IStrategyBase
{
virtual ResultType DoSomething(SomeType someParameter) = 0;
// could expose some MyUglyClass members, since
// derived classes wouldn't inherit friendship
};
class ActualImplementation: public MyUglyClass::IStrategyBase
{
ResultType DoSomething(SomeType someParameter) override
{
// Do actual work
}
}
class YetAnotherImplementation: public MyUglyClass::IStrategyBase
{
ResultType DoSomething(SomeType someParameter) override
{
// Doing something really tricky & clever for corner cases
}
}
编译器当然会抱怨,因为 IStrategyBase
不可访问;我可以通过将 ActualImplementation
和 YetAnotherImplementation
与 IStrategyBase
一起 fwd 声明到头文件中来解决这个问题,但我宁愿避免这种情况,因为如果需要新策略。
我也可以在 public 范围内声明 IStrategyBase
,但我更愿意将其保密以避免其他人弄乱它。
当然我假设非 fwd 声明的 subclasses 不会继承与 MyUglyClass
的友谊,所以我将不得不公开相关数据 IStrategyBase
受保护的成员。
有什么办法可以做到这一点吗?
编辑:
感谢所有发表评论的人,我意识到即使在 public 范围内声明,也没有人可以乱用 IStrategyBase
class,因为 class 定义会被埋没在实现文件中也是如此。我现在想知道是否可以让派生的 classes 访问 MyUglyClass
的内部结构,而不必将它们与 IStrategyBase
一起 fwd 声明。我想答案是 "no",因为友谊不会被继承,但也许我还缺少一些 C++ perk。
如果你想隐藏任何实现细节,你可以使用 pImpl idiom(指向实现的指针)又名不透明指针https://en.wikipedia.org/wiki/Opaque_pointer所以你可以像这样更改你的代码
-- 头文件
#include <memory>
class MyUglyClass
{
MyUglyClass();
~MyUglyClass(); // destructor must be only declared to avoid problems
// with deleting just forwarded inner class
private:
class Impl;
std::unique_ptr<Impl> pImpl;
};
-- 实现文件
class MyUglyClass::Impl
{
class IStrategyBase;
IStrategyBase* sPtr;
class ActualImplementation; // now these classes safely hidden inside .cpp
class YetAnotherImplementation; // Nobody can reach them.
};
class MyUglyClass::Impl::IStrategyBase
{
virtual ResultType DoSomething(SomeType someParameter) = 0;
// could expose some MyUglyClass members, since
// derived classes wouldn't inherit friendship
};
class ActualImplementation: public MyUglyClass::Impl::IStrategyBase
{
ResultType DoSomething(SomeType someParameter) override
{
// Do actual work
}
};
class YetAnotherImplementation: public MyUglyClass::Impl::IStrategyBase
{
ResultType DoSomething(SomeType someParameter) override
{
// Doing something really tricky & clever for corner cases
}
};
MyUglyClass::MyUglyClass() : pImpl(new Impl()) {}
MyUglyClass::~MyUglyClass() {} // let the unique_ptr do its work
一种可能性(这不是 pimpl 惯用法,只是一种可访问性 hack):
class MyUglyClass
{
private:
struct Impl; // Is automatically "friend struct Impl;"
class IStrategyBase;
IStrategyBase* sPtr;
// class ActualImplementation; // this is what I'd like to avoid
// class YetAnotherImplementation; // as above
// blah blah blah
};
class MyUglyClass::IStrategyBase
{
public:
virtual int DoSomething(int someParameter) = 0;
// could expose some MyUglyClass members, since
// derived classes wouldn't inherit friendship
};
struct MyUglyClass::Impl
{
class ActualImplementation: public MyUglyClass::IStrategyBase
{
int DoSomething(int someParameter) override
{ (void) someParameter; return 1;}
};
class YetAnotherImplementation: public MyUglyClass::IStrategyBase
{
int DoSomething(int someParameter) override
{ (void) someParameter; return 2; }
};
};
int main() {}
我目前正在重构一些遗留代码,并希望将多个 if...elseif... 语句分解为一系列 classes 实现各种策略。
因为我必须访问原始对象的内部结构,所以我将把新的 classes 声明为嵌套的 classes;因为外部世界没有人可以访问它们,所以我更愿意在私有范围内声明它们。
为了尽可能少地暴露实现细节,我想知道是否可以在头文件中仅前向声明基本策略class,并将所有子class es 声明在实现文件中。代码示例如下:
-- 头文件
class MyUglyClass
{
private:
class IStrategyBase;
IStrategyBase* sPtr;
// class ActualImplementation; // this is what I'd like to avoid
// class YetAnotherImplementation; // as above
// blah blah blah
};
-- 实现文件
class MyUglyClass::IStrategyBase
{
virtual ResultType DoSomething(SomeType someParameter) = 0;
// could expose some MyUglyClass members, since
// derived classes wouldn't inherit friendship
};
class ActualImplementation: public MyUglyClass::IStrategyBase
{
ResultType DoSomething(SomeType someParameter) override
{
// Do actual work
}
}
class YetAnotherImplementation: public MyUglyClass::IStrategyBase
{
ResultType DoSomething(SomeType someParameter) override
{
// Doing something really tricky & clever for corner cases
}
}
编译器当然会抱怨,因为 IStrategyBase
不可访问;我可以通过将 ActualImplementation
和 YetAnotherImplementation
与 IStrategyBase
一起 fwd 声明到头文件中来解决这个问题,但我宁愿避免这种情况,因为如果需要新策略。
我也可以在 public 范围内声明 IStrategyBase
,但我更愿意将其保密以避免其他人弄乱它。
当然我假设非 fwd 声明的 subclasses 不会继承与 MyUglyClass
的友谊,所以我将不得不公开相关数据 IStrategyBase
受保护的成员。
有什么办法可以做到这一点吗?
编辑:
感谢所有发表评论的人,我意识到即使在 public 范围内声明,也没有人可以乱用 IStrategyBase
class,因为 class 定义会被埋没在实现文件中也是如此。我现在想知道是否可以让派生的 classes 访问 MyUglyClass
的内部结构,而不必将它们与 IStrategyBase
一起 fwd 声明。我想答案是 "no",因为友谊不会被继承,但也许我还缺少一些 C++ perk。
如果你想隐藏任何实现细节,你可以使用 pImpl idiom(指向实现的指针)又名不透明指针https://en.wikipedia.org/wiki/Opaque_pointer所以你可以像这样更改你的代码
-- 头文件
#include <memory>
class MyUglyClass
{
MyUglyClass();
~MyUglyClass(); // destructor must be only declared to avoid problems
// with deleting just forwarded inner class
private:
class Impl;
std::unique_ptr<Impl> pImpl;
};
-- 实现文件
class MyUglyClass::Impl
{
class IStrategyBase;
IStrategyBase* sPtr;
class ActualImplementation; // now these classes safely hidden inside .cpp
class YetAnotherImplementation; // Nobody can reach them.
};
class MyUglyClass::Impl::IStrategyBase
{
virtual ResultType DoSomething(SomeType someParameter) = 0;
// could expose some MyUglyClass members, since
// derived classes wouldn't inherit friendship
};
class ActualImplementation: public MyUglyClass::Impl::IStrategyBase
{
ResultType DoSomething(SomeType someParameter) override
{
// Do actual work
}
};
class YetAnotherImplementation: public MyUglyClass::Impl::IStrategyBase
{
ResultType DoSomething(SomeType someParameter) override
{
// Doing something really tricky & clever for corner cases
}
};
MyUglyClass::MyUglyClass() : pImpl(new Impl()) {}
MyUglyClass::~MyUglyClass() {} // let the unique_ptr do its work
一种可能性(这不是 pimpl 惯用法,只是一种可访问性 hack):
class MyUglyClass
{
private:
struct Impl; // Is automatically "friend struct Impl;"
class IStrategyBase;
IStrategyBase* sPtr;
// class ActualImplementation; // this is what I'd like to avoid
// class YetAnotherImplementation; // as above
// blah blah blah
};
class MyUglyClass::IStrategyBase
{
public:
virtual int DoSomething(int someParameter) = 0;
// could expose some MyUglyClass members, since
// derived classes wouldn't inherit friendship
};
struct MyUglyClass::Impl
{
class ActualImplementation: public MyUglyClass::IStrategyBase
{
int DoSomething(int someParameter) override
{ (void) someParameter; return 1;}
};
class YetAnotherImplementation: public MyUglyClass::IStrategyBase
{
int DoSomething(int someParameter) override
{ (void) someParameter; return 2; }
};
};
int main() {}