Публичный член без наследства - PullRequest
3 голосов
/ 15 июня 2011

У меня есть базовый класс, который выглядит примерно так:

class Base
{
public:
  typedef std::shared_ptr<Base> ptr_t;
  typedef std::weak_ptr<Base> wptr_t;

  enum class Type { foo, bar, baz };

  Type x;
  // ...
};

Я бы хотел, чтобы эти внутренние типы были общедоступными, чтобы я мог делать такие вещи, как Base::ptr_t my_ptr(new Base); и так далее. Но если я сделаю новый класс, как этот ...

class Derived : public Base
{
  // ...
};

к сожалению, Derived::ptr_t по-прежнему является базовым указателем. Я бы хотел, чтобы Derived публично наследовал x от Base, но не наследовал ptr_t, wptr_t или Type. Например

Derived a;
a.x = Base::Type::foo; // this should work
a.x = Derived::Type::foo; // but I want this to fail

Возможно ли это, возможно, хоть какое-то магическое использование friend или virtual или что-то в этом роде?

Ответы [ 3 ]

4 голосов
/ 15 июня 2011

Просто переопределите тип:

class Derived {
  typedef int Type;
};

Это не позволит использовать Derived::Type (как личное, так и typedef ed)

3 голосов
/ 15 июня 2011
class Derived : public Base
{
  // This is now private
  using Base::ptr_t;
  using Base::wptr_t;
  // ...
};
0 голосов
/ 15 июня 2011

Основываясь на ответах iammilind и Luc Danton, вот что я придумал:

class Base
{
private:
  // only 'BaseClass' is allowed to derive from Base
  Base() { }
  friend class BaseClass;
public:
  typedef std::shared_ptr<Base> ptr_t;
  typedef std::weak_ptr<Base> wptr_t;

  enum class Type { foo, bar, baz };

  Type x;
  // ...
};

class BaseClass : public Base
{
private:
  // make all the raw_Base types private
  using Base::ptr_t;
  using Base::wptr_t;
  using Base::Type;
};

class Derived : public BaseClass
{
  // define as usual, and now all is well in the world.
};

// now, to test it
class Derived2 : public Base { }; // fails

Derived d;
d.x = Derived::Type::foo; // fails
d.x = Base::Type::foo; // works
// Which is exactly what I wanted.

Насколько я могу судить, единственная проблема этого решения заключается в том, что оно добавляет новый и потенциально запутанный класс. Класс определен таким образом, что его нельзя реально использовать неправильно - сам по себе Base не может быть получен, кроме как с помощью BaseClass, но, тем не менее, BaseClass является непривлекательной частью пространства имен.

Однако, для конкретного фрагмента кода, в котором я собираюсь использовать это, я, оказывается, уже использую эквивалент BaseClass для решения несвязанной проблемы. Так что эта BaseClass техника вполне подходит для моих целей.

...