zoukankan      html  css  js  c++  java
  • C++不完整的类型

    今天写C++primer 5th中文版第422页的程序时,出现了”不允许使用不完整的类型“的错误,下面我就用类A 与 类B 作为代表,重现一下该错误,并且提出解决方案。

    一、带问题的类设计A:

    1、类A放在A.h 与 A.cpp中

    2、由于B需要访问A的私有成员,故声明B是其友元类

    3、A中需要利用自身作为参数去创建一个新的B类实例。

    代码如下:A.cpp中就是一个空的析构函数的实现。。。没什么,我把主要实现都写在了A.h中

     1 #pragma once
     2 #include<iostream>
     3 
     4 class B; // 声明B 从而能够在下文声明为友元类
     5 class A
     6 {
     7 public:
     8     friend class B; // 声明B为友元类
     9     A(int a) :data(a){}
    10 
    11     B Pirnt() // 打印一行文字并且调用B的构造函数:B(A &a, int secParam = 5)创建一个B的实例
    12     {
    13         std::cout << "hehe " << std::endl;
    14         return B(*this);
    15     }
    16     ~A();
    17 private:
    18     int data;
    19 };

    二、带问题的类设计B

    1、B 接受一个A 引用参数,达成构造B的目的

    同样的,B.cpp中也是一个空的构造函数与一个空的析构函数,下面展示的是B.h中的代码:

     1 #pragma once
     2 #include "A.h"
     3 class B
     4 {
     5 public:
     6     B(A &a, int secParam = 5) :data(a.data){}
     7     B();
     8     ~B();
     9 
    10 private:
    11     int data;
    12 };

    三、问题提示:

    在A.h的第11 与 14行使用B的地方提示”B不是完整的数据类型“

    四、分析

    首先,我们需要在类A中将B声明为友元类,此时类B尚未定义,故仅在class A前面声明了class B;然后在此利用B进行代码编写,但是带来了问题:

    这种声明叫做 前向声明,它在声明之后,定义之前的这段时间,它都是不完整的,对于类A中的代码来讲,他们不知道B什么时候定义,所以编译器直接认为B是不完整的。。。

    如果分别在A.h与B.h中包含对方的头文件,又造成了循环包含。

    五、解决方案。

    1、将A  B写在一个头文件中

    2、声明A,定义B

    3、定义A

    代码:

    A.h

    #pragma once
    #include<iostream>
    class A;  // 声明A
    
    class B
    {
    public:
        B(A &a, int secParam = 5); // 只可声明,不能在此处定义,具体定义在B.cpp中写
        ~B();
    
    private:
        int data;
    };
    
    
    class A
    {
    public:
        friend class B; // 声明B为友元类
        A(int a) :data(a){}
    
        B Pirnt() // 打印一行文字并且调用B的构造函数:B(A &a, int secParam = 5)创建一个B的实例
        {
            std::cout << "hehe " << std::endl;
            return B(*this);
        }
        ~A();
    private:
        int data;
    };

    B.cpp

    #include "A.h"
    B::B(A &a, int secParam) :data(a.data)
    {
    }
    
    B::~B()
    {
    }

    对于A.cpp,还是空的构造函数与析构函数

    原因:

    1、上文说道在类声明与定义之间的时间内,其是不完整的,不可使用的,但是  可以定义指向这种类型的指针和引用,可以声明(不能定义)以不完整类型作为参数或者返回类型的函数。

    故,可以先在B中的构造函数里使用 A& 这个参数.

    不过使用A&作为参数的那个构造函数的实现(定义)需要在cpp中写,因此执行到CPP的时候,A已经是完整的了。

    2、 执行到A时,B的各成员声明已经完整。

  • 相关阅读:
    C#下给数字前面补0的方法
    Notepad++ xml 文件不能语法着色的问题解决
    excel 技巧
    编译时报警 implicit declaration of function
    配置ASP.NET平台时遇到的“访问IIS元数据库失败”解决方案
    用360安全卫士批量本地快速给系统打补丁【转贴】
    新雨情系统随笔
    我的开发博客开通了
    JQuery资料
    IGNORE_DUP_KEY = OF的作用
  • 原文地址:https://www.cnblogs.com/tntboom/p/4404286.html
Copyright © 2011-2022 走看看