在c++中,类只包含(默认情况下)私有成员有什么用吗



类的成员在c++中默认为私有。

因此,我想知道创建一个类是否有任何可能的用途,该类的所有成员(变量和函数)默认设置为private。

换句话说,如果没有关键字publicprotectedprivate,是否存在任何有意义的类定义?

有一种用于访问保护的模式,基于这种类:有时它被称为密钥模式(另请参阅clean C++细粒度朋友等效模式?(答案:Attorney Client Idiom)和如何命名这种面向密钥的访问保护模式?)。

只有密钥类的朋友可以访问protectedMethod():

// All members set by default to private
class PassKey { friend class Foo; PassKey() {} };
class Bar
{
public:
  void protectedMethod(PassKey);
};
class Foo
{
  void do_stuff(Bar& b)
  {
    b.protectedMethod(PassKey());  // works, Foo is friend of PassKey
  }
};
class Baz
{
  void do_stuff(Bar& b)
  {
    b.protectedMethod(PassKey()); // error, PassKey() is private
  }
};

标记调度。它在迭代器类别标记的标准库中使用,以便选择对某些迭代器分类可能更有效的算法。例如,std::distance可以这样实现:(事实上,它在gnu-libstdc++中几乎完全是这样实现的,但我对它进行了一些修改以提高可读性)

template<typename Iterator>
typename iterator_traits<Iterator>::difference_type
distance(Iterator first, Iterator last)
{
      return __distance(first, last,
             typename iterator_traits<Iterator>::iterator_category());
}

其中,__distance是一个函数,它被重载以更有效地执行std::random_access_iterator_tag(这是一个空结构,但也可以很容易地成为一个类),只需使用last - first,而不是计算从firstlast需要多少增量的默认行为。

应用程序范围内的资源获取?

#include <iostream>
class C {
    C() {
        std::cout << "Acquire resource" << std::endl;
    }

    ~C() {
        std::cout << "Release resource" << std::endl;
    }
    static C c;
};

C C::c;
int main() {
    return 0;
}

正如下面的评论中所说,我介意一个工业应用程序在程序运行时不得不"锁定"一些硬件设备。但人们可能会发现它的其他用途,因为毕竟,它只是一些"退化"的情况或RAII。


关于在声明块之外使用"private"方法:我在这里使用一个静态成员。因此,它被声明为,此时私有成员可以访问。您不限于构造函数/析构函数。您甚至可以(ab)使用静态方法,然后使用流畅的接口调用私有实例方法:

class C {
    C() { std::cout << "Ctor " << this << std::endl; }
    ~C() { std::cout << "Dtor" << this << std::endl; }
    static C* init(const char* mode) {
        static C theC;
        std::cout << "Init " << mode << std::endl;
        return &theC;
    }
    C* doThis() {
        std::cout << "doThis " << std::endl;
        return this;
    }
    C* doThat() {
        std::cout << "doThat " << std::endl;
        return this;
    }
    static C *c;
};

C *C::c = C::init("XYZ")
            ->doThis()
            ->doThat();
int main() {
    std::cout << "Running " << std::endl;
    return 0;
}

该代码仍然有效(因为在C::c声明时,所有C成员都可以访问)。并将产生类似的东西:

Ctor 0x601430
Init XYZ
doThis 
doThat 
Running 
Dtor0x601430

有意义吗?好的做法?可能不会,但这是:

class DataContainer {
    friend class DataUser;
    int someDataYouShouldNotWorryAbout;
};
class DataUser {
public:
    DataUser() {
        container.someDataYouShouldNotWorryAbout = 42;
    }
private:
    DataContainer container;
};
不,创建一个没有公共成员变量和/或函数的类是没有意义的,因为没有办法访问类中的任何内容。即使没有明确说明,继承也是私有的。

当然,您可以按照建议使用friend,但它会创建不必要的卷积。


另一方面,如果您使用struct而不是class来定义一个类,那么您就可以将所有内容都公开。这也许是有道理的。

例如:

struct MyHwMap {
  unsigned int field1 : 16;
  unsigned int field2 : 8;
  unsigned int fieldA : 24;
};

一个公认的丑陋案例,来自许多年前,不是在C++中,但这个想法仍然适用:

运行库中存在错误。事实上,修复有问题的代码会导致其他问题,所以我写了一个例程,找到了有问题的部分代码,并用一个有效的版本替换了它。最初的化身除了它的创造之外根本没有任何接口。

派生类可以是完全私有的,甚至其重新定义/实现基类方法的虚拟方法也是如此。

要构建实例,您可以拥有友元类或函数(例如工厂),和/或在注册表中注册类/实例。

这方面的一个例子可以是表示";模块";在图书馆里。例如,wxWidgets有类似的东西(它们是注册的并执行init/deinit)。

相关内容

最新更新