类定义中的多个公共/私有关键字

时间:2014-03-08 05:39:23

标签: c++ c++11

我在类定义中看到过多个公共和私有关键字,如下例所示:

class myClass
{
  public:
    void func1(){}
  public:
    void func2(){}
  private:
    int x;
    int y;
  private:
    int z;
    int baz;
};

这个(如果有的话)的实际用途是什么?是否有 任何 这种情况有用吗?

5 个答案:

答案 0 :(得分:3)

  

是否有任何可能有用的情况?

我可以想到一种情况,否则会出现问题:

 class myClass
{
  public:
    void func1(){}
  public:
    void func2(){}
  COORDINATES;    // <-- Note the macro here!
  private:
    int z;
    int baz;
};

,在COORDINATES宏扩展后,变为:

class myClass
{
  public:
    void func1(){}
  public:
    void func2(){}
  private:
    int x;
    int y;
  private:
    int z;
    int baz;
};

如果不允许多个private / public个关键字,那么这样做会非常痛苦。虽然使用宏并不是好习惯;也没有为宏之后出现的所有成员静默地引入访问修饰符。然而,它可能对生成C ++源代码的RAD工具很有用。

我只能猜到为什么你会在人类写作课上看到它。我的猜测是编码不好;作者可能想表达一大块数据属于一起和/或希望能够在类定义中上下移动那些块,以及相应的访问修饰符(private/protected/public)。

答案 1 :(得分:1)

我会用一段代码远离我对这个答案的评论更进一步。

class myClass {

    // initializers etc
    public:
        myClass();
        ~myClass();

    // signal processing
    public:
        void modifyClass();
    private:
        float signalValue;

    // other class responsibilities
    public:
        void doWork();
    private:
        void workHelper();
};

等等。我不会说这是一个坚固的设计课程,但它是展示课程不同功能的好方法。

答案 2 :(得分:1)

另一种用途是当您想拥有特定的销毁订单时。让我们考虑两种情况:

  1. 不好的情况

    // Auxiliary class
    Class StorageCleaner {
    public:
        StorageCleaner(ExternalStorage* storage) : storage_(storage);
        ~StorageCleaner() { storage_->DeleteEverything(); }
    private:
        ExternalStorage* const storage_;  // Not owned
    }
    
    // Class with bad declaration order
    Class ExternalStorageWrapper {
    public:
        ExternalStorageWrapper(ExternalStorage* storage) : cleaner_(storage) {
            pointer_to_storage_.reset(storage);
        }
        const StorageCleaner cleaner_;  
    private:
        std::unique_ptr<ExternalStorage> pointer_to_storage_;
    
        // Other data which should be private
        int other_int;
        string other_string;
        .... 
    };
    

    当现有ExternalStorageWrapper对象超出范围时会发生什么?

    • 首先是ExternalStorageWrapper析构函数 销毁其他数据
    • 然后它将销毁pointer_to_external_storage_指向的外部存储空间(因为字段在反向声明顺序中被销毁)。

    • 然后它将尝试销毁cleaner_

    • 但是它自己的析构函数中的清理器试图操纵已经被破坏的外部存储器!

  2. 好案例

    // Class StorageCleaner same as before
    ...
    
    // Class with better declaration order
    Class ExternalStorageWrapper {
    private:
        std::unique_ptr<ExternalStorage> pointer_to_storage_;
    
    public:
        ExternalStorageWrapper(ExternalStorage* storage) : cleaner_(storage) {
            pointer_to_storage_.reset(storage);
        }
        const StorageCleaner cleaner_;
    
    private:
        // Other data which should be private
        int other_int;
        string other_string;
            .... 
    };
    

    当现有ExternalStorageWrapper对象超出范围时,会发生什么情况?

    • ExternalStorageWrapper析构函数将首先销毁其他数据。
    • 然后它将尝试销毁cleaner_。清除程序将使用DeleteEverything()指针指向仍然存在的存储空间storage_。{/ li>
    • 最后,存储通过pointer_to_storage_销毁。
  3. 我实际上不得不在公司中调试这样的问题,所以虽然很少见,但这种特殊情况可能会发生。

答案 3 :(得分:0)

为了清楚起见,我遇到了一个用例。如下例所示,class1继承了base类,该类包含class1需要实现的纯虚函数。为了表明method1中的class1来自某个其他类class1的继承(例如base),而不是class1自己的函数,我们使用了另一个public来说明这一点:

class base {
public:
   virtual void method1() = 0;
}

class class1: base {
public:
   myOwnMethod1();
   myOwnMethod2();
public: /* base interface */
   method1();

答案 4 :(得分:0)

刚刚阅读完这些示例。希望这可以有助于定义多个关键字。 我们并不需要做太多假设,因为这是我目前的当前问题,但是消耗了以下内容:

class IOHandler {
public:
    enum COLOR_DEFINITIONS : unsigned char
    {
        BLACK,
        DARK_ER_BLUE,
        DARK_GREEN,
        DARK_SKY_BLUE,
        DARK_RED,
        DARK_PINK,
        DARK_YELLOW,
        DARK_WHITE,
        DARK_GREY,
        DARK_BLUE,
        BRIGHT_GREEN,
        BRIGHT_SKY_BLUE,
        BRIGHT_RED,
        BRIGHT_PINK,
        BRIGHT_YELLOW,
        BRIGHT_WHITE
    };
    template <typename dtEX>
    void showOutputEx(dtEX literalOutput, _COLOR_OUTPUT textColorSet = {COLOR_DEFINITIONS::BRIGHT_WHITE , COLOR_DEFINITIONS::BRIGHT_YELLOW}, bool appendOutputType = true, OUTPUT_TYPE levelOutput = OUTPUT_TYPE::OUTPUT_NORMAL, EMBRACE_TYPE embraceOutputType = EMBRACE_TYPE::EMBRACE_OUTPUT_LEVEL, ...);
    // !                                  ^^^^^^^^^^^^^^ Doesn't detect the struct being referenced at which is at below.
private:
    typedef struct colorProps // This is the struct that the public function where trying to get referenced at but failed to do so.
    {
        unsigned char C_BG = 0,
                      C_FG = 0;
    } _COLOR_OUTPUT;
};

错误代码。

identifier "_COLOR_OUTPUT" is undefined.

在这一点上,我的intelliSense一直抱怨_COLOR_OUTPUT在公共类范围内未定义。 最可能的解决方案是将结构放入公共范围而不是私有范围内。 但是我不想。

发生这种情况的原因是由于编译器从上至下读取文件。任何宣布的内容 需要参考的应该放在最上面,并且应该可以解决问题。因为我不想把所有私有类的函数和变量弄得一团糟 在上面。我应该在顶部声明另一个说明符,以便任何需要引用的公共函数都可以看到它。

因此,解决方案如下:(将所有可引用的变量和struct移到类的顶部,以便识别任何私有和公共函数参数引用。)

class IOHandler {
// Private Class Scope for Variables and Structure
private:
    typedef struct colorProps // This is the struct we move at the top for recognizing references.
    {
        unsigned char C_BG = 0,
                      C_FG = 0;
    } _COLOR_OUTPUT;
public:
    enum COLOR_DEFINITIONS : unsigned char
    {
        BLACK,
        DARK_ER_BLUE,
        DARK_GREEN,
        DARK_SKY_BLUE,
        DARK_RED,
        DARK_PINK,
        DARK_YELLOW,
        DARK_WHITE,
        DARK_GREY,
        DARK_BLUE,
        BRIGHT_GREEN,
        BRIGHT_SKY_BLUE,
        BRIGHT_RED,
        BRIGHT_PINK,
        BRIGHT_YELLOW,
        BRIGHT_WHITE
    };
    template <typename dtEX>
    void showOutputEx(dtEX literalOutput, _COLOR_OUTPUT textColorSet = {COLOR_DEFINITIONS::BRIGHT_WHITE , COLOR_DEFINITIONS::BRIGHT_YELLOW}, bool appendOutputType = true, OUTPUT_TYPE levelOutput = OUTPUT_TYPE::OUTPUT_NORMAL, EMBRACE_TYPE embraceOutputType = EMBRACE_TYPE::EMBRACE_OUTPUT_LEVEL, ...);
    // !                                  ^^^^^^^^^^^^^^ Now recognizable reference.
private:
    ... // Any other functions, excerpt.
};