栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++继承时的一些语法规则

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++继承时的一些语法规则

自生成方法

众所周知,C++类有四种函数如果不显示定义会自动生成:构造函数、析构函数、拷贝构造函数、运算符重载(operator = )。在继承时,很多特殊情况也就出在这四类函数中。
继承中派生类内包含了基类内所有方法和属性,只是由于private 权限修饰不能在派生类中直接调用而已。但是基类构造函数明明就算设置成public,在子类对象中也是不能直接使用的。这其实就很容易理解:基类和派生类的构造、析构、拷贝构造甚至都不重名,运算符重载参数也一般直接指定的本对象的类型(如果想直接使用父类的运算符重载函数,不在子类中显示声明,编译会报错)。

#include 
 
class CMyString : public std::string
{
    public: 
 
    CMyString( void ){};  
 
    virtual ~CMyString( void ){};   
 
       
    using std::string::operator=;
 
};
 
void main()
{    
    CMyString strMine; 
    strMine = "我继承了等号运算符~";
}

所以一般的使用范例是直接在派生类的相关函数中显示的调用父类函数

class base{
public:
    virtual ~base();
    base(const char *pStr);
    base(const base &other);
    virtual void CallFunction() ;
public:
    char *m_pbase;
};

base::base(const char *pStr){
    if (pStr) {
        long iLen = strlen(pStr)+1;
        m_pbase = new char[iLen];
        memset(m_pbase, 0, iLen);
        strcpy(m_pbase, pStr);
    }}

base::~base(){
    if (m_pbase) {
        delete [] m_pbase;
        m_pbase = NULL;
    }
}

base::base(const base &other){
    if (m_pbase) {
        delete m_pbase;
        m_pbase = NULL;
    }
    long iLen = strlen(other.m_pbase)+1;
    m_pbase = new char[iLen];
    memset(m_pbase, 0, iLen);
    strcpy(m_pbase, other.m_pbase);
}
class Child:public base{
public:
    ~Child();
    Child(const char *pStr , const char *pbase);
    Child(const Child &other);
public:
    char *m_pChild;
};

Child::Child(const char *pStr , const char *pbase):base(pbase){//初始化列表中调父类构造函数
    if (pStr) {
        long iLen = strlen(pStr)+1;
        m_pChild = new char[iLen];
        memset(m_pChild, 0, iLen);
        strcpy(m_pChild, pStr);
    }
}

Child::Child(const Child &other):base(other){//调父类拷贝构造函数
    if (m_pChild) {
        delete m_pChild;
        m_pChild = NULL;
    }
    long iLen = strlen(other.m_pChild)+1;
    m_pChild = new char[iLen];
    memset(m_pChild, 0, iLen);
    strcpy(m_pChild, other.m_pChild);
}


Child::~Child(){
    if (m_pChild) {
        delete [] m_pChild;
        m_pChild = NULL;
    }
}
其他方法

而对于一般成员方法来说,值得注意的就是类内的重载,派生类的重写,还有方法重名时的隐藏。重载是指同类内同名方法不同参数(注意和返回值无关)。
重写是指有父子关系的两个类中同名方法相同参数,甚至返回值都要相同。重写的场景发生在父类的方法不再适用用子类,子类中使用同名方法重新实现一次(当然可以使用 ‘:’先运行一次父类的函数),是方便子类创建对象后运行不同于父类的有自己特性的方法,如果重写的函数在父类中添加了virtual,则是方便多态:即方便用父类指针调用子类对象有自己特性的方法。
覆盖是指有父子关系的两个类中同名方法。比如基类中有三个funcName(…)函数,只要子类中定义了同名的(只要名字相同)funcName()函数,则子类对象中所有父类的funcName函数都无法访问了。
办法1:在派生类里覆盖所有基类的的fcn方法,在方法体里,直接调用base::funcName,但是这样太麻烦了,每一个都要覆盖。
办法2:使用using。只需要在派生类的public下,using base::funcName; ,就达到了办法1的效果。

class D1 : public base{
  
public:
  using base::fcn;//使用using后,就把base里的,所有fcn为名字的成员方法,都引入到D1里面,所以就可以使用D1的对象来调用base里的任何fcn为名字的成员方法了。
  int fcn(){
    std::cout << "D1 fcn()" << std::endl;
  }
};
使用接口

C++的多继承带来有名的菱形继承问题,如果如果能使用纯虚函数,纯虚类。将通过将构造函数的权限设置为protected达到模拟java接口的目的。在初次实现时尽量将has-a的方法抽象出去变成接口,可以有效的降低系统中出现难以溯源的继承问题。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/384997.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号