CPP:仅允许通过使用者派生的基本成员访问

cpp: permit base member access only via derived by consumer

提问人: 提问时间:8/10/2023 最后编辑:wohlstad 更新时间:8/10/2023 访问量:61

问:

我有一个应用程序,其中 Base 是对象的工厂类,应根据模板对以不同的方式创建对象。但是,只有非常特殊(可数无限)数量的模板对才有意义。对于每个合理的对,我都有一个(有时)模板化的派生工厂类。由于需要正确选择模板对,因此使用 Base Factory 容易出错。

我的问题是:如何防止消费者直接使用Base Factory?

template<typename T1, typename T2>
class Base{
  Base()=delete;
public:
  // many public static routines
  T1 static foo(){ return 1; }
  T2 static bar(){ return 2; }
};

template<typename T1>
class Derived: public Base<T1,float>{
  // hopefully very little code, or none at all, as of now.
};

int main(){ // main is the consumer
  Base<int,float>::foo(); // prevent
  Derived<int>   ::foo(); // permit
}

我希望编译器拒绝/thow/err 在 main 中带有注释“prevent”的行。我想要 Base<..>::foo 和 Base<..>::bar 除非通过 Derived<.. 进行访问,否则消费者不能直接访问。>.我曾希望这个概念可以用于这个目的。但是,它不会自然地从非静态情况转移到静态情况。virtual

C++ 模板 继承 private-members

评论

0赞 wohlstad 8/10/2023
我回滚了您的编辑,因为您不应该编辑您的问题以使退出答案无效。
0赞 Fabio says Reinstate Monica 8/10/2023
@wohlstad 我不认为编辑会使您的答案无效。它说“如果......就好了”,但这不是一个严格的要求。在我看来,没有必要回滚它。
0赞 wohlstad 8/10/2023
@FabiosaysReinstateMonica从OP的评论中,我在下面的回答中了解到这对OP实际上很重要。但再想一想,我同意可能不需要回滚。如果您认为第 2 版可以使问题更清晰,请随时回滚到第 2 版。

答:

0赞 wohlstad 8/10/2023 #1

您可以创建方法,并通过带有语句的类公开它:fooprotectedDerivedpublicusing

template<typename T1, typename T2>
class Base {
    Base() = delete;
protected:
    T1 static foo() { return 1; }
    T2 static bar() { return 2; }
};

template<typename T1>
class Derived : public Base<T1, float> {
public:
    using Base<T1, float>::foo;
};

int main() { // main is the consumer
    Base<int, float>::foo(); // prevent
    Derived<int>   ::foo(); // permit
}

现场演示 - Godbolt

评论

0赞 8/10/2023
谢谢。这已经很整洁了。然而,有点挑剔的是,Derived 的实现需要为 Base 中的每个例程实现一行。有没有一种解决方案可以避免这种情况?,这样我就可以向 Base 添加任意多个函数,而无需每次都递增 Derived 的代码?
0赞 wohlstad 8/10/2023
我不知道有这样的选择。
0赞 wohlstad 8/10/2023
请注意,您不必立即修改所有派生类。您可以简单地将方法置于保护状态,然后仅公开您在任何 defived 类中实际使用的方法(编译器可以帮助识别所有这些位置)。Base
0赞 Pepijn Kramer 8/10/2023
好吧(明确的)正确性应该是 IMO 比一点点打字更重要。你 但是,在我看来,它也使用继承来管理可见性,这似乎是对继承的滥用。