zoukankan      html  css  js  c++  java
  • C++ 类声明 类前置声明范例

    转载自http://www.cnblogs.com/staring-hxs/p/3244251.html

    在编写C++程序的时候,偶尔需要用到前置声明(Forward declaration)。下面的程序中,带注释的那行就是类B的前置说明。这是必须的,因为类A中用到了类B,而类B的声明出现在类A的后面。如果没有类B的前置说明,下面的程序将不同通过编译,编译器将会给出类似“缺少类型说明符”这样的出错提示。

    代码一:
    // ForwardDeclaration.h
    #include <iostream>
    using namespace std;
    class B;             // 这是前置声明(Forward declaration)
    class A
    {
    private:
             B* b;
    public:
             A(B* b):b(b){}
    };
    
    class B
    {
    };
    
    // Main.cpp
    #include "ForwardDeclaration.h"
    int main(int argc, char** argv)
    {
             B* b = new B();
             A* a = new A(b);
             delete a;
             delete b;
             return 0;
    }

    上面程序可以顺利编译和运行(几乎没有做什么,也没有输出)。

    是不是有了前置说明就万事大吉了呢?我们看看下面的代码(带阴影部分的代码是新增加的):

    代码二:
    // ForwardDeclaration.h
    #include <iostream>
    using namespace std;
    class B;             // 这是前置声明(Forward declaration)
    class A
    {
    private:
             B* b;
    public:
             A(B* b):b(b){}
    void someMethod() { b->someMethod(); // (1) }
    };
    
    class B
    {
    public:
    void someMethod()
    { cout << "something happened..." << endl; }
    };
    
    // Main.cpp
    #include "ForwardDeclaration.h"
    int main(int argc, char** argv)
    {
             B* b = new B();
             A* a = new A(b);
        a->someMethod();
        delete a;
        delete b;
        return 0;
    }

    一编译,发现代码(1)处出错。出错提示往往包括(不同的编译器给出的提示会有所不同):

    1. 使用了未定义的类型B;

    2. “->somemethod”的左边必须指向类/结构/联合/泛型类型

    原因:

    1. (1)处使用了类型B的定义,因为调用了类B中的一个成员函数。前置声明class B;仅仅声明了有一个B这样的类型,而并没有给出相关的定义,类B的相关定义,是在类A后面出现的,因此出现了编译错误;

    2. 代码一之所以能够通过编译,是因为其中仅仅用到B这个类型,并没有用到类B的定义。

    解决办法是什么?

    将类的声明和类的实现(即类的定义)分离。如下所示:

    // ForwardDeclaration.h   类的声明
    #include <iostream>
    using namespace std;
    class B;             // 这是前置声明(Forward declaration)
    class A
    {
    private:
             B* b;
    public:
            A(B* b);
    void someMethod();
    };
    
    class B
    {
    public:
    void someMethod();
    };
    
    // ForwardDeclaration.cpp        类的实现
    #include "ForwardDeclaration.h"
    A::A(B* b):b(b)
    {
    
    }
    void A::someMethod() { b->someMethod(); } void B::someMethod() { cout << "something happened..." << endl; } // Main.cpp #include "ForwardDeclaration.h" int main(int argc, char** argv) { B* b = new B(); A* a = new A(b); a->someMethod();      delete a;
    delete b;      return 0; }

    结论:

    前置声明只能作为指针或引用,不能定义类的对象,自然也就不能调用对象中的方法了。

    而且需要注意,如果将类A的成员变量B* b;改写成B& b;的话,必须要将b在A类的构造函数中,采用初始化列表的方式初始化,否则也会出错。关于这点

    见:

    特殊数据类型成员变量的初始化

    但是我的测试还是不行

  • 相关阅读:
    Javascript FP-ramdajs
    微信小程序开发
    SPA for HTML5
    One Liners to Impress Your Friends
    Sass (Syntactically Awesome StyleSheets)
    iOS App Icon Template 5.0
    React Native Life Cycle and Communication
    Meteor framework
    RESTful Mongodb
    Server-sent Events
  • 原文地址:https://www.cnblogs.com/dobben/p/7440745.html
Copyright © 2011-2022 走看看