类 链中的转化

Conversions in a chain of classes

我有一个对象SSS0S1S2 层组成...就像一堆可堆叠的抽屉。

我想创建一个模板链 类 ABC 这样:

  1. 它们代表 S 对象不同层的代理。
  2. 即使在模板实例化期间,C 也可以转换为 B,后者可以转换为 A
  3. ABC有不同的方法集。

问题是如果我使用public继承,那么C会得到AB的方法。

测试:

#include <iostream>
// Library
template <typename T>
class A {
public:
    void a() {std::cout << "a\n"; }
    int s_{0};
};

template <typename T>
class B : public A<T> {
public:
    void b() {std::cout << "b\n"; }
};

template <typename T>
class C : public B<T> {
public:
    void c() {std::cout << "c\n"; }
};

// User of library write a function like this
template <typename T>
void foo(A<T>& a) { a.a(); }

// The problem:
int main() {
    C<int> c;
    foo(c);
    c.a();  // <--- how to hide this?
    return 0;
}

"Just" 层 Si

需要 0 + 1 + 2 + ... + i 个转换运算符

或者一个模板转换运算符,如果它们的属性都相同的话。

但这仍然需要一些方法来控制转换。

#include <iostream>

template <typename T>
class A {
public:
    A(int& layer) : layer_(layer) {}
    void a() {std::cout << "a\n"; }

    int s_{0};
private:
    int& layer_;
};

template <typename T>
class B {
public:
    B(int& layer) : a_(layer) { }
    template <template<typename> class X, typename T2>
    operator X<T2>() { return a_; }
    void b() {std::cout << "b\n"; }

private:
    A<T> a_;
};

template <typename T>
class C {
public:
    C(int& layer) : b_(layer) {}
    template <template<typename> class X, typename T2>
    operator X<T2>() { return b_; }
    void c() {std::cout << "c\n"; }

private:
    B<T> b_;
};

template <typename T>
class D {
public:
    D(int& layer) : c_(layer) {}
    template <template<typename> class X, typename T2>
    operator X<T2>() { return c_; }
    void c() {std::cout << "c\n"; }

private:
    C<T> c_;
};

template <template<typename> class X, typename T>
void foo(X<T>& a) {
    A<T>(a).a();
}

int main() {
    int v = 1;
    D<int> d(v);
    foo(d);
    return 0;
}

我不确定我是否明白你想要什么。但一种方法是更改​​派生 class 中基 class 成员的访问级别。例如:

template <typename T>
class C : public B<T> {
public:
    void c() { std::cout << "c\n"; }
private:
    using A::a;  // <-- reduce access level of base class member
};