精华内容
下载资源
问答
  • golang继承swig导出的c++基类 项目原来使用c++实现了底层逻辑,为了方便业务方使用,现在需要支持golang语言的sdk。经过调研了解到swig可以将C++导出接口类供其他脚本语言或者高级编程语言调用,本文基于swig实现...

    golang继承swig导出的c++基类

    项目原来使用c++实现了底层逻辑,为了方便业务方使用,现在需要支持golang语言的sdk。经过调研了解到swig可以将C++导出接口类供其他脚本语言或者高级编程语言调用,本文基于swig实现C++类导出golang的接口类,然后在golang中利用struct实现继承。

    为了更好地演示,本文利用简单的C++类进行描述。

    首先定义C++的基类和一个辅助类,后面go会利用struct派生于基类BaseCase,辅助类用于调用派生类的函数。

    // BaseCase.h
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    
    class BaseCase
    {
    public:
        BaseCase() {}
        virtual ~BaseCase() {}
        BaseCase(const BaseCase& rhs) {
            m_caseName = rhs.m_caseName;
        }
        virtual void Run() {cout << "run the case in baseCase class." << endl;}
    
    public:
        string m_caseName;
    };
    
    class CaseRunner
    {
    public:
        BaseCase* _baseCase_;
    
    public:
        CaseRunner():_baseCase_(0) {}
        void RegisterCase(BaseCase *bc) {_baseCase_ = bc;}
        void run() {if (_baseCase_) _baseCase_->Run();}
    };
    

    编写swig.i文件

    // swig.i
    %module(directors="1") baseCase
    %{
     #include "BaseCase.h"
    %}
    %include "std_string.i"
    %include "std_map.i"
    %feature("director") BaseCase;
    %include "BaseCase.h"

    然后利用swig命令行将导出BaseCase和CaseRunner的Golang接口类

    // swig command line
    swig -go -cgo -intgosize 64 -c++ swig.i

    执行完上面个的命令之后,会生成对应的swig_wrap.cxx,swig_wrap.h,baseCase.go

    然后编写test.go文件

    package main
    
    import (
        "fmt"
        . "baseCase"
    )
    
    type TestCase1Class interface {
        BaseCase
        deleteBaseCase()
        IsTestCase1Class()
    }
    
    type testCase1Class struct {
    	BaseCase  // 这个是swig导出来的interface接口
    }
    
    func (caseClass_ *testCase1Class) IsTestCase1Class() {}
    
    func (caseClass_ *testCase1Class) deleteBaseCase() {
        DeleteDirectorBaseCase(caseClass_.BaseCase)
    }
    
    type TestClass struct {
    	p BaseCase
    }
    
    func NewGoTestCase1Class() TestCase1Class {
        om := &TestClass{}
        p := NewDirectorBaseCase(om)
        om.p = p
        return &testCase1Class{BaseCase: p}
    }
    
    func (caseClass_ *TestClass) Run() {
        fmt.Println("start to run caseClass ...")
        caseClass_.case1()
        caseClass_.case2()
    }
    
    // case1
    func (caseClass_ *TestClass) case1() {
    	fmt.Println("run caseClass 1")
    }
    
    // case2
    func (caseClass_ *TestClass) case2() {
    	fmt.Println("run caseClass 2")
    }
    
    func main() {
        goCase := NewGoTestCase1Class()
        caseRuner := NewCaseRunner()
        caseRuner.RegisterCase(goCase)
        caseRuner.Run()
        return
    }

    执行打包命令,即可以编译一个test的可执行文件

    >> go build test.go
    >> ./test
    start to run caseClass ...
    run caseClass 1
    run caseClass 2

    参考:http://www.swig.org/Doc3.0/Go.html#Go_class_inheritance

    展开全文
  • C++ 基类和派生类

    2014-08-01 17:29:15
    转自C++ 基类和派生类 本讲讨论基类和派生类的基本概念。  通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。我们称已存在的...

    整理自C++ 基类和派生类


      通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。我们称已存在的用来派生新类的类为基类,又称为父类。由已存在的类派生出的新类称为派生类,又称为子类。
      在C++中,一个派生类可以从一个基类派生,也可以从多个基类派生。从一个基类派生的继承称为单继承;从多个基类派生的继承称为多继承。

    派生类的定义格式

      单继承的定义格式如下:

       class <派生类名>:<继承方式><基类名>
        {
         <派生类新定义成员>
        };
      其中,<派生类名>是新定义的一个类的名字,它是从<基类名>中派生的,并且按指定的<继承方式>派生的。

      <继承方式>常使用如下三种关键字给予表示:
       public 表示公有基类;
       private 表示私有基类;
       protected 表示保护基类;

      多继承的定义格式如下:

       class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
        {
         <派生类新定义成员>
        };

      可见,多继承与单继承的区别从定义格式上看,主要是多继承的基类多于一个。

    派生类的三种继承方式

      公有继承(public)、私有继承(private)、保护继承(protected)是常用的三种继承方式。

      1. 公有继承(public)

      公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的。

      2. 私有继承(private)

      私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。

      3. 保护继承(protected)

      保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元访问,基类的私有成员仍然是私有的。

      下面列出三种不同的继承方式的基类特性和派生类特性。
    继承方式 基类特性 派生类特性
    公有继承 public public
    protected
    private
    protected
    不可访问
    私有继承 public private
    protected
    private
    private
    不可访问
    保护继承 public protected
    protected
    private
    protected
    不可访问

      为了进一步理解三种不同的继承方式在其成员的可见性方面的区别,下面从三种不同角度进行讨论。

      对于公有继承方式:

      (1) 基类成员对其对象的可见性:
      公有成员可见,其他不可见。这里保护成员同于私有成员。
      (2) 基类成员对派生类的可见性:
      公有成员和保护成员可见,而私有成员不可见。这里保护成员同于公有成员。
      (3) 基类成员对派生类对象的可见性:
      公有成员可见,其他成员不可见。
      所以,在公有继承时,派生类的对象可以访问基类中的公有成员;派生类的成员函数可以访问基类中的公有成员和保护成员。这里,一定要区分清楚派生类的对象和派生类中的成员函数对基类的访问是不同的。

      对于私有继承方式:

      (1) 基类成员对其对象的可见性:
      公有成员可见,其他成员不可见。
      (2) 基类成员对派生类的可见性:
      公有成员和保护成员是可见的,而私有成员是不可见的。
      (3) 基类成员对派生类对象的可见性:
      所有成员都是不可见的。
      所以,在私有继承时,基类的成员只能由直接派生类访问,而无法再往下继承。

      对于保护继承方式:

      这种继承方式与私有继承方式的情况相同。两者的区别仅在于对派生类的成员而言,对基类成员有不同的可见性。

      上述所说的可见性也就是可访问性。关于可访问性还有另的一种说法。这种规则中,称派生类的对象对基类访问为水平访问,称派生类的派生类对基类的访问为垂直访问。
      一般规则如下
       公有继承时,水平访问和垂直访问对基类中的公有成员不受限制;
       私有继承时,水平访问和垂直访问对基类中的公有成员也不能访问;
       保护继承时,对于垂直访问同于公有继承,对于水平访问同于私有继承。
      对于基类中的私有成员,只能被基类中的成员函数和友元函数所访问,不能被其他的函数访问。

    基类与派生类的关系

      任何一个类都可以派生出一个新类,派生类也可以再派生出新类,因此,基类和派生类是相对而言的。
      基类与派生类之间的关系可以有如下几种描述:

       1. 派生类是基类的具体化

       类的层次通常反映了客观世界中某种真实的模型。在这种情况下,不难看出:基类是对若干个派生类的抽象,而派生类是基类的具体化。基类抽取了它的派生类的公共特征,而派生类通过增加行为将抽象类变为某种有用的类型。

       2. 派生类是基类定义的延续

       先定义一个抽象基类,该基类中有些操作并未实现。然后定义非抽象的派生类,实现抽象基类中定义的操作。例如,虚函数就属此类情况。这时,派生类是抽象的基类的实现,即可看成是基类定义的延续。这也是派生类的一种常用方法。

       3. 派生类是基类的组合

       在多继承时,一个派生类有多于一个的基类,这时派生类将是所有基类行为的组合。

      派生类将其本身与基类区别开来的方法是添加数据成员和成员函数。因此,继承的机制将使得在创建新类时,只需说明新类与已有类的区别,从而大量原有的程序代码都可以复用,所以有人称类是“可复用的软件构件”。

    展开全文
  • 文章目录c/c++ 基类析构函数为什么必须定义为虚函数?1 现象2 原因剖析3 扩展 c/c++ 基类析构函数为什么必须定义为虚函数? 1 现象 在c++ 实现多态时,我们经常会用到用基类来操作派生类,这样多便于上层接口的统一,...

    c/c++ 基类析构函数为什么必须定义为虚函数?

    1 现象

    在c++ 实现多态时,我们经常会用到用基类来操作派生类,这样多便于上层接口的统一,而把基类定义为虚函数,就是为了释放基类句柄时只析构基类而不析构派生类的情况发生。
    下面列举三种使用情况

    • 基类析构函数不是虚函数,不使用多态,创建派生类对象。
    • 基类析构函数不是虚函数,使用多态,创建派生类对象。
    • 基类析构函数是虚函数,使用多态,创建派生类对象。

    以上几种情况对应代码如下:

    #include <iostream>
    #include <stdio.h>
    using namespace std;
    class BaseClass
    {
    public:
        BaseClass()
        {
    
        }
        ~BaseClass()
        {
            printf("fucn %s line %d\n",__FUNCTION__,__LINE__);
        }
        void do_something(void)
        {
            printf("fucn %s line %d\n", __FUNCTION__, __LINE__);
        }
    };
    
    class DeriveClass : public BaseClass
    {
    public:
        DeriveClass()
        {
        }
        ~DeriveClass()
        {
            printf("fucn %s line %d\n", __FUNCTION__, __LINE__);
        }
        void do_something(void)
        {
            printf("fucn %s line %d\n", __FUNCTION__, __LINE__);
        }
    };
    
    
    class BaseClass2 
    {
    public:
        BaseClass2()
        {
    
        }
        ~BaseClass2()
        {
            printf("fucn %s line %d\n",__FUNCTION__,__LINE__);
        }
        void do_something2(void)
        {
            printf("fucn %s line %d\n", __FUNCTION__, __LINE__);
        }
    };
    
    class DeriveClass2 : public BaseClass2
    {
    public:
        DeriveClass2()
        {
        }
        ~DeriveClass2()
        {
            printf("fucn %s line %d\n", __FUNCTION__, __LINE__);
        }
        void do_something2(void)
        {
            printf("fucn %s line %d\n", __FUNCTION__, __LINE__);
        }
    };
    
    class BaseClass3 
    {
    public:
        BaseClass3()
        {
    
        }
        virtual ~BaseClass3()
        {
            printf("fucn %s line %d\n",__FUNCTION__,__LINE__);
        }
        void do_something3(void)
        {
            printf("fucn %s line %d\n", __FUNCTION__, __LINE__);
        }
    };
    
    class DeriveClass3 : public BaseClass3
    {
    public:
        DeriveClass3()
        {
        }
        ~DeriveClass3()
        {
            printf("fucn %s line %d\n", __FUNCTION__, __LINE__);
        }
        void do_something3(void)
        {
            printf("fucn %s line %d\n", __FUNCTION__, __LINE__);
        }
    };
    
    
    int main(void)
    {
    	// 第一种情况没有使用多态,直接创建一个派生类指针,然后 new一个派生类对象给它,在delete 派生类指针时会自动析构,先析构派生类,再析构基类,没有内存泄漏
        DeriveClass *p = new DeriveClass();
        p->do_something();
        delete p;
       // 第二种情况使用多态,直接创建一个基类指针,然后 new一个派生类对象给它,在delete 派生类指针时会自动析构,只是析构基类的对象,而派生类并没有析构,造成内存泄漏
        BaseClass2 *p2 = new DeriveClass2();
        p2->do_something2();
        delete p2;
       // 第三种情况使用多态,直接创建一个基类指针,然后 new一个派生类对象给它,在delete 派生类指针时会自动析构,先析构派生类,再析构基类,没有内存泄漏
        BaseClass3 *p3 = new DeriveClass3();
        p3->do_something3();
        delete p3;
        
        return 0;
    }
    
    

    运行结果如下:

    fucn do_something line 33
    fucn ~DeriveClass line 29
    fucn ~BaseClass line 13
    fucn do_something2 line 51
    fucn ~BaseClass2 line 47
    fucn do_something3 line 84
    fucn ~DeriveClass3 line 96
    fucn ~BaseClass3 line 80
    

    2 原因剖析

    想要回收一个对象申请的资源,那么就需要调用析构函数,虽然我们没有显示地调用析构函数,但是编译器会帮我们默认的执行析构函数,比如说在上例中我们通过 new 的方式创建一个对象,new的时候回自动调用构造函数(这也就是malloc和new的主要区别之一,有机会详细讨论),而在 delete时编译器会自动执行析构函数,帮我们释放掉相关的资源。
    通过上面的实验我们发现:如果基类的析构函数不是虚函数,在我们使用多态的情况下,我们在delete 基类对象并不会释放派生类的资源,只会释放基类的资源,原因如下:
    基类指针指向了派生类的对象,而基类中的析构函数是非 virtual 的,虚函数是动态绑定的基础,动态绑定是多态的基础,动态绑定是发生在程序运行时。如果基类的析构函数不是virtual的,就不会发生动态绑定绑定,指针的静态类型为基类指针,因此delete时只会调用基类的析构函数,而不会调用派生类的析构函数,这样派生类申请的资源(动态申请的资源)得不到释放,从而造成内存泄漏,因此为了防止上述情况的发生我们统一将基类的析构函数写成 virtual 虚析构函数

    3 扩展

    构造函数为什么不能是虚函数?
    动态绑定和静态绑定的问题?
    c++虚函数实现原理?
    关于以上问题,有机会进行讨论

    展开全文
  • C++基类指针

    2019-06-22 19:21:00
    基类指针可以指向派生类对象,派生类对象不能指向基类对象 这样可以生成基类指针的数组,然用指向不同的派生类对象,然后用同一个数组循环,这样既可在一个循环中调用不同派生类的方法。 ps a.func a必须为类对象 ...

    基类指针可以指向派生类对象,派生类对象不能指向基类对象

    这样可以生成基类指针的数组,然用指向不同的派生类对象,然后用同一个数组循环,这样既可在一个循环中调用不同派生类的方法。

    ps a.func a必须为类对象

    b->func b必须为指针

    展开全文
  • ()C++基类的虚析构函数 #include&lt;iostream&gt; using namespace std; class Base { private: int i; public: Base(){ cout &lt;&lt; "Base count " &lt;&lt; endl; } ...
  • C++基类成员函数访问派生类对象的基类成员问题,很奇怪的现象,在网上也没有找到相应的说明。 主要是问题太难描述了。 Talk is cheap, show you the code: class Derived; class Base { public: void func...
  • C++基类、派生类的初始化

    千次阅读 2016-08-25 15:10:23
    C++基类、派生类的初始化class base { // ... }class derived : public base { // ... }///////////////////////////////////////////////////////////// derived A;执行derived A时,推测 基类和派生类的构造顺序...
  • 来源:我的博客站 OceanicKang |《C++ 基类和子类构造器析构器的执行顺序》 例子 #include &amp;amp;amp;amp;lt;iostream&amp;amp;amp;amp;gt; class BaseClass { public: BaseClass(); ~Base...
  • c++基类指针指向继承类调用继承类函数   类里面重载运算符&gt;&gt;, 需要使用友元函数,而友元函数,不能作为虚函数。 所以,基类指针无法直接调用继承类里重构的 &gt;&gt; ; 使用...
  • 请问大家c++基类派生和成员函数在使用的过程中有什么区别 优缺点
  • C/C++基类的析构函数为什么必须定义为虚函数?

    千次阅读 多人点赞 2018-09-05 15:26:24
    C/C++基类的析构函数为什么必须定义为虚函数?   为什么基类的析构函数是虚函数? 在实现多态时,当用基类操作派生类,在析构时防止只析构基类而不析构派生类的状况发生。 (1)第一种情况:没有多态,创建派生...
  • C++基类派生类

    2019-08-01 22:19:27
    基类和派生类 1、::和: ::后接成员函数或变量 :继承 类的构造函数不能继承,(即使继承了它的名字和派生类的名字也不一样,不能成为派生类的构造函数,更不能成为普通的成员函数) Student::Student(char...
  • 函数隐藏是指派生类中函数与基类中的函数同名,但是这个函数在基类中并没有被定义为虚函数,这种情况就是函数的隐藏。 所谓隐藏是指使用常规的调用方法,派生类对象访问这个函数时,会优先访问派生类中的这个函数,...
  • C++语言中,一个派生类可以从一个基类派生,也可以从多个基类派生。从一个基类派生的继承称为单继承;从多个基类派生的继承称为多继承。 派生类的定义格式 单继承的定义格式如下: class <派生类名>:<...
  • C++基类和派生类

    千次阅读 2016-10-11 19:13:27
    一个基类派生出一个派生类,它又做另一个派生类的基类,则原来基类为该派生类的间接基类基类与派生类之间的关系可以有如下几种描述: 1 派生类是基类的具体化 类的层次通常反映了客观世界中某种真实
  • 想验证一下C++ 基类private纯虚函数 在派生类中是否可以实现,若可以,该怎么实现 a.先在网上搜到一下资源 1.【转】“纯虚函数可以设计成私有的,不过这样不允许在本类之外的非友元函数中直接调用它,子类中只有...
  • C++ 基类私有成员会被继承吗

    万次阅读 多人点赞 2015-11-05 00:51:24
    1.派生类间接访问继承私有成员在...在派生类还是能够通过调用基类的共有函数的方式来间接地访问基类的私有成员,包括私有成员变量和私有成员函数。考察如下程序。#include &lt;iostream&gt; using namespace s
  • C++ 基类和派生类(转)

    2009-09-24 17:05:00
    C++ 基类和派生类(转)2001-08-28 08:42作者:--出处:pcvc.net责任编辑:方舟 本讲讨论基类和派生类的基本概念。 通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的...
  • 基类: 派生类: 1.派生类到基类的类型转换 可以把派生类的对象当成基类的对象使用 可以将基类的指针或者引用绑定到派生类对象的基类部分(派生类到基类的类型转换) 2.派生类的构造函数 派生类的构造函数:每...
  • 类型转换 公有派生类对象可以被当做基类的对象使用,反之则不可 通过基类对象名、指针只能使用从基类继承的成员
  • 这个已有的类称为基类,新建的类称为派生类。 基类 & 派生类 一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数。定义一个派生类,我们使用一个类派生列表来指定基类。类派生列表以一个或多个...
  • (1)将子类指针赋值给基类指针时,不需要进行强制类型转换,c++编译器将自动进行类型转换。因为子类对象也是一个基类对象。 (2)将基类指针赋值给子类指针时,需要进行强制类型转换,c++编译器将不自动进行类型...
  • C++基类加virtual的作用

    2020-06-07 22:35:43
    } 只释放了基类资源,本身没有释放,因为基类的析构不是虚函数,不在虚函数表中,基类指针只会找到自己的析构 MyBase MyA ~MyBase 加了virtual之后 class MyBase { public: MyBase(){cout ;} virtual ~MyBase(){...
  • c++: C++ 基类-继承-单继承-多继承

    千次阅读 2018-04-13 11:32:10
    1. 基类 官方解释是:在面向对象设计中,被定义为包含所有实体共性的class类型,被称为“基类”。 这个解释通俗的说就是:里面有public和private或者protected之类具体函数和变量定义的类,例如: class Base {...
  •  在公用继承、私有继承和保护继承中,只有公用继承能较好地保留基类的特征,它保留了除构造函数和析构函数以外的基类所有成员,基类的公用或保护成员的访问权限在派生类中全部都按原样保留下来了,在派生类外可以...
  • C++ 基类与派生类之间的相互引用、赋值问题 这是我第一次真正的自己写C++的文章,前两天在网上找基类与派生类之间的赋值,引用,指针之间的问题是没有找到一个详细介绍的,这也正是我决定写这篇文章的目的。关于...
  • C++基类与派生类

    2013-01-05 13:32:54
    派生类要先调用基类的构造函数,而不能直接覆盖基类的构造函数。 所以在派生类不能再成员初始化列表中初始化基类的成员 见如下例子: class Base { public: Base(double dNum) : nBase(1) , dBase...
  • 我们常用基类指针指向派生类对象来实现多态性。 基类指针只能访问到基类中含有的公有成员。 成员如果是数据成员的话访问的是基类的版本(如果派生类中含有相同名字的数据成员的话)。 对于已经被重写的方法成员...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 21,822
精华内容 8,728
关键字:

c++基类

c++ 订阅