zoukankan      html  css  js  c++  java
  • 如何利用c++编写不能被继承、但可以在类外定义对象的类

     1 #include <iostream>
     2 #include<string>
     3 #include<map>
     4 #include<vector>
     5 #include"thread_pool.h"
     6 
     7 
     8 using namespace std;
     9 template<class T>
    10 class base{
    11     friend T;/// friend class
    12 private:
    13     base(){}
    14     ~base(){}
    15 };
    16 
    17 class derived : public virtual base<derived>
    18 {
    19 public:
    20     derived(){}
    21     void show(){
    22         cout<<"can be instanced,but can not be inherited"<<endl;
    23     }
    24     ~derived(){}
    25 };
    26 
    27 class dderived : public derived{
    28 public:
    29     dderived(){}
    30     ~dderived(){}
    31 };
    32 
    33 
    34 
    35 int main()
    36 {
    37     cout << "Hello world!" << endl;
    38     derived d;
    39     d.show();
    40     return 0;
    41 }
    View Code

    只要把类A的构造函数和析构函数定义为private类型,那么就不能在类A外部建立类的对象,也不能将类A作为基类进行继承。
    因为如果继承,建立对象的时候调用基类的构造函数,因为是private的,所以派生类调用基类构造函数的时候,将会链接失败--》不能继承,但是我们也就不能在类外定义对象了。

    -------------

    class base{
        friend T;/// friend class
    private:
        base(){}
        ~base(){}
    };

    class derived : public virtual base<derived>
    {
    public:
        derived(){}
        void show(){
            cout<<"can be instanced,but can not be inherited"<<endl;
        }
        ~derived(){}
    };

    我们可以看到drived类虚继承(!!!这个 virtual 不能不能不能去掉)自base类,在模板展开的时候derived类被声明为base类的友类,因此可以访问base中的private的部分。

    所以可以调用base中被定义为private的构造和析构,定义derived类型的对象是没有任何问题的。

    ----

    class dderived : public derived{}

    dderived 是不能被实例化的。why???    <此处应该由  深入探究c++对象模型 这本书>的。

    c++对象模型中,构造顺序是,虚拟基类---基类---虚拟指针---初始化列表中的---构造函数 内部的语句

    在我们的例子中,就是虚拟基类(base)---基类(derived)---虚拟指针---初始化列表中的---构造函数(dderived(){}),

    所以我们就可以知道先会dderived调用虚拟基类base的构造函数,但是对于dderived来说,base的构造函数是不能访问的,因为base的构造函数被定义为private,

    并且ddrived不是base的友员类,所以在用dderive构造对象的时候,链接错误,也就是说明drived是不能够被继承的。

    下面显示的链接错误《这里应该有  深入理解c++对象模型》

    ||=== Build: Debug in rpc (compiler: GNU GCC Compiler) ===|
    /home/lizhen/codeblocks/rpc/main.cpp||In constructor ‘dderived::dderived()’:|
    /home/lizhen/codeblocks/rpc/main.cpp|13|error: ‘base<T>::base() [with T = derived]’ is private|
    /home/lizhen/codeblocks/rpc/main.cpp|28|error: within this context|
    /home/lizhen/codeblocks/rpc/main.cpp|14|error: ‘base<T>::~base() [with T = derived]’ is private|
    /home/lizhen/codeblocks/rpc/main.cpp|28|error: within this context|
    /home/lizhen/codeblocks/rpc/main.cpp||In destructor ‘dderived::~dderived()’:|
    /home/lizhen/codeblocks/rpc/main.cpp|14|error: ‘base<T>::~base() [with T = derived]’ is private|
    /home/lizhen/codeblocks/rpc/main.cpp|29|error: within this context|
    ||=== Build failed: 6 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

    ============================

    但是如果derived不是virtual inherit自base类的话,就不会发生链接错误。

  • 相关阅读:
    HttpUtils 用于进行网络请求的工具类
    Java 身份证工具类
    MD5加密Java工具类
    Nginx配置文件详细说明
    java统计abacbacdadbc中的每个字母出现的次数,输出格式是:a(4)b(3)c(3)d(2)
    mysql查询今天,昨天,近7天,近30天,本月,上一月数据的SQL
    Java随机生成常用汉字验证码
    Google Kaptcha验证码的使用
    Linux查看CPU和内存使用情况
    myql导入导出命令
  • 原文地址:https://www.cnblogs.com/li-daphne/p/5505639.html
Copyright © 2011-2022 走看看