【问题标题】:inheritance of private member variable from class template从类模板继承私有成员变量
【发布时间】:2018-11-08 17:48:22
【问题描述】:

我做了一个如下所示的类模板,作为其他类继承的基类,它可以正常工作。

但我的问题是,即使我将“操作”类的“保护”更改为“私有”,代码仍然可以编译,即使 Matmul(继承了“操作”类)正在修改名为“edgeIn”的向量,该向量被声明为'私人'。

我不明白为什么应该允许这样的事情...... 编译器不应该对此触发错误消息吗? (派生类不应该修改基类的私有成员)

template<typename T>
class Operation{
private: //Would compile fine even if I change this to 'private!'
    class edge{
    public:
        edge(Tensor<T> tensor, Operation<T> &from, Operation<T> &to) {
            this->tensor = tensor;
            this->from = from;
            this->to = to;
        }
        Operation<T> from;
        Operation<T> to;
        Tensor<T> tensor;
    };
    std::vector<edge> edgeIn; //edges as inputs of this operation
    std::vector<edge> edgeOut; //edges as outputs of this operation
private:
    //disable copy constructor (NOT ALLOWED)
    Operation(Operation<T>& rhs) = default;
    //disable move operator (NOT ALLOWED)
    Operation<T>& operator=(Operation<T> &rhs) = default;
    int operationId;
};

template<typename T>
class Matmul: public Operation<T>{
public:
    Matmul(std::initializer_list<std::pair<Tensor<T>, Operation<T>>> args);
};

template<typename T>
//from Operation<T>, to This operation
Matmul<T>::Matmul(std::initializer_list<std::pair<Tensor<T>, Operation<T>>> args){
    for(auto elem: args){
        typename Operation<T>::edge info{elem.first, elem.second, *this};
        this->edgeIn.emplace_back(info); //modifying member of base class
    }
}

【问题讨论】:

  • 你有那个模板类的实例化吗?
  • 请提供minimal reproducible example。除非必要(存在它的实例化),否则不会编译模板。
  • @AlgirdasPreidžius -- 模板已部分编译。这里的问题可能是直到模板被实例化(比如Matmul&lt;float&gt;),编译器并不确定edge 是私有的;可能有一个特化 Operation&lt;float&gt; 和一个名为 edge 的公共类型。当然,您是对的,需要一个完整的示例。
  • @PeteBecker 是的,我知道它们在某种程度上是经过编译的(至少 - 检查了代码的语法)。但是,由于我不知道如何以简明扼要的方式表达这一点,所以我决定保留评论原样,因为它不是评论的重点(即:minimal reproducible example request )。

标签: c++


【解决方案1】:

在您显示的代码中,它是允许的,因为它没有错。这是一个更简单的例子:

template <class Ty>
class base {
    int i; // private
};

template <class Ty>
class derived : base {
    void set(int ii) { i = ii; }
};

此时,如果你写

derived<int> di;
di.set(3); // illegal: i is not accessible

如您所料,您将收到访问错误。

但原始模板并没有错,因为代码可能会这样做:

template <>
class base<int> {
public:
    int i;
};

现在你可以写了

derived<int> di;
di.set(3);

没关系,因为ibase&lt;int&gt; 中是公开的。你还是不会写

derived<double> dd;
dd.set(3); // illegal: i is not accessible

【讨论】:

  • “这是允许的,因为它没有错”有史以来最好的报价!
  • 感谢您的回答,很抱歉没有提供完整的示例。我认为编译器应该告诉我是否有任何尝试修改基类的私有成员(即使它只在类模板中)。事实证明你是对的。如果我实例化用“私有”编写的代码,编译器会抱怨。
猜你喜欢
  • 1970-01-01
  • 2013-02-12
  • 2012-12-25
  • 2016-12-03
  • 2016-01-28
  • 1970-01-01
  • 2018-11-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多