iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++中关于多态实现和使用方法
  • 615
分享到

C++中关于多态实现和使用方法

2024-04-02 19:04:59 615人浏览 八月长安
摘要

目录赋值兼容实例多态静多态动多态格式实例override纯虚函数含有虚函数的析构函数注意事项RTTItypeidtypecast多态实现虚函数一般继承(no override)一般继

都说 c++面向对象的语言,其中的面向对象主要包括三部分:继承,封装,多态。继承和封装我们之前就简单介绍过,这里主要对多态的使用方法做一个简单说明。

赋值兼容

赋值兼容说的是在使用基类对象的地方可以使用公有继承类的对象来代替。赋值兼容是一种默认的行为,不需要进行显式转换就能够实现。

就比如在派生类拷贝构造函数的参数初始化列表中,我们会直接使用派生类对象作为基类拷贝构造函数的参数,而不会报错,这就是赋值兼容的表现。赋值兼容主要表现在:

  • 派生类的对象可以赋值给基类对象
  • 派生类的对象可以初始化基类的引用
  • 派生类对象的地址可以赋值给指向基类的指针
  • 但,发生赋值兼容之后,只能使用从基类继承的成员

实例

#include <iOStream>
 
using namespace std;
 
class PERSON
{
public:
    PERSON(char *name_ = "***",char sex_ = '*')
        :name(name_),sex(sex_){}
    void display()
    {
        cout<<"The name is "<<name<<endl;
        cout<<"The sex is "<<sex<<endl;
    }
protected:
    char *name;
    char sex;
};
 
class STUDENT:public PERSON
{
public:
    STUDENT(char *name_ = "***",char sex_ = '*',char *num_ = "100")
        :PERSON(name_,sex_),num(num_){}
    void display()
    {
        cout<<"The name is "<<name<<endl;
        cout<<"The sex is "<<sex<<endl;
        cout<<"The num is "<<num<<endl;
    }
private:
    char *num;
};
 
int main()
{
    STUDENT st("zhangsan",'x',"100");
    st.display();
    PERSON per = st;
    per.display();
    PERSON &per2 = st;
    per2.display();
    PERSON *per3 = &st;
    per3->display();
 
    return 0;
}

结果为:

The name is zhangsan
The sex is x
The num is 100
The name is zhangsan
The sex is x
The name is zhangsan
The sex is x
The name is zhangsan
The sex is x

上边的程序可以看出,基类对象,引用和指针都可以使用派生类对象或者指针进行赋值,从而进行访问。

其实也可以将基类指针强制转换为派生类指针,进行访问,但这种形式绝不是赋值兼容:

int main()
{
    PERSON per("zhangsan",'x');
    per.display();
 
    STUDENT *st = static_cast<STUDENT *>(&per);
    st->display();
 
    return 0;
}

结果为:

The name is zhangsan
The sex is x
The name is zhangsan
The sex is x
The num is 夽@

上边的程序中,是将基类的指针强制转换派生类的指针,从而调用派生类的对象。

  • 从实际上来说,该过程只是将以基类地址其实的一段内存交给了派生类的指针,因为类对象只存储数据成员,因此能够对应访问到从基类继承到的数据成员。
  • 但同时不确定原来基类成员后边的空间有什么东西,结果为出现部分乱码。
  • 如果将基类和派生类位置对调就是赋值兼容了。

多态

C++ 中的多态主要说的是,在面向对象中,接口的多种不同的实现方式。

静多态

C++ 中的多态是接口多种不同的实现方式。而我们之前提到过的函数重载也是接口的多种不同的实现方式,因此也可以称之为多态,只是函数重载是在编译阶段通过 name mangling 实现的,所以叫做静多态。

动多态

而不在编译阶段而是在运行阶段决定的多态就称为动多态。动多态的形成条件为:

  • 父类中有虚函数
  • 子类 override 父类中的的虚函数
  • 通过已被子类对象赋值的父类指针或引用,调用公有接口

格式

class classname
{
    virtual datatype func(argu);
}

实例

#include <iostream>
 
using namespace std;
 
class PERSON
{
public:
    PERSON(char *name_ = "***",char sex_ = '*')
        :name(name_),sex(sex_){}
    virtual void display()
    {
        cout<<"The name is "<<name<<endl;
        cout<<"The sex is "<<sex<<endl;
    }
protected:
    char *name;
    char sex;
};
 
class STUDENT:public PERSON
{
public:
    STUDENT(char *name_ = "***",char sex_ = '*',char *num_ = "100")
        :PERSON(name_,sex_),num(num_){}
    virtual void display()
    {
        cout<<"The name is "<<name<<endl;
        cout<<"The sex is "<<sex<<endl;
        cout<<"The num is "<<num<<endl;
    }
protected:
    char *num;
};
 
class POSTGRADUATE:public STUDENT
{
public:
    POSTGRADUATE(char *name_ = "***",char sex_ = '*',char *num_ = "***",char *job_ = "***")
        :STUDENT(name_,sex_,num_),job(job_){}
    virtual void display()
    {
        cout<<"The name is "<<name<<endl;
        cout<<"The sex is "<<sex<<endl;
        cout<<"The num is "<<num<<endl;
        cout<<"The job is "<<job<<endl;
    }
protected:
    char *job;
};
 
int main()
{
    POSTGRADUATE po("zhsangsan",'x',"100","paper");
    po.display();
 
    PERSON *per = &po;
    per->display();
    STUDENT *st = &po;
    st->display();
 
    return 0;
}

结果为:

The name is zhsangsan
The sex is x
The num is 100
The job is paper
The name is zhsangsan
The sex is x
The num is 100
The job is paper
The name is zhsangsan
The sex is x
The num is 100
The job is paper

在基类中声明虚函数时需要使用 virtual 关键字,在类外实现虚函数时,不用再加 virtual

在派生类中重新定义此函数的过程称为 override,此过程要求函数的要素全都不能发生改变,包括函数名,返回值类型,形参个数和类型,只有函数体可以改变

当基类中的函数成员被声明为 virtual 时,其派生类中完全相同的函数都会变为虚函数,原则上派生类中的虚函数不用使用 virtual 关键字,但是为了程序的可读性,可以在派生类的对应函数前加上 virtual

定义一个指向基类的指针,并使其指向其子类对象的地址,通过该指针调用虚函数,此时调用的就是指针变量指向的对象

子类中 override 的函数,可以为任意访问类型

通过多态就避免了赋值兼容的问题

override

在虚函数的使用中,需要在派生类中 override 基类中的虚函数,表明该函数是从基类 override 得到的,override 的含义表明:

  • override 的函数要素全都不能发生改变
  • 包括函数名,返回值类型,形参个数和类型
  • 只有函数体可以改变

而有时为了可读性,也为了防止编写时出错,可以通过在函数后添加 override 关键字表明这是 override 得到的。如上边的例子中:

virtual void display() override

使用上边的形式可以严格语法书写。

纯虚函数

对于一些抽象基类来说,我们并不需要在其中的虚函数中编写什么语句,因此可以将之写成纯虚函数。

class classname
{
    virtual datatype func(argu) = 0;
}

如上例所示,可以将 STUDENT 中的 display 函数定义为纯虚函数:

virtual void display() = 0;

只是此时不能够调用 STUDENT 中的该函数了。

对于纯虚函数而言:

  • 含有纯虚函数的类,称为抽象基类,不能够创建该类对象,该类只能被继承,提供公共接口
  • 纯虚函数的声明形式就包含了声明和实现
  • 如果一个类中声明了纯虚函数,而在派生类中没有定义该函数,则该虚函数在派生类中仍然是纯虚函数,派生类仍然为抽象基类,这意味着在第一次继承的时候一定要定义该函数
  • 从这个角度看,才算是虚函数的正确用法,直接用来声明为纯虚基类,从而被继承

含有虚函数的析构函数

含有虚函数的类,析构函数也应该声明为虚函数。

#include <iostream>
 
using namespace std;
 
class PERSON
{
public:
    PERSON(char *name_ = "***",char sex_ = '*')
        :name(name_),sex(sex_){}
    virtual void display()
    {
        cout<<"The name is "<<name<<endl;
        cout<<"The sex is "<<sex<<endl;
    }
    ~PERSON(){cout<<"PERSON"<<endl;}
protected:
    char *name;
    char sex;
};
 
class STUDENT:public PERSON
{
public:
    STUDENT(char *name_ = "***",char sex_ = '*',char *num_ = "100")
        :PERSON(name_,sex_),num(num_){}
    virtual void display()
    {
        cout<<"The name is "<<name<<endl;
        cout<<"The sex is "<<sex<<endl;
        cout<<"The num is "<<num<<endl;
    }
    ~STUDENT(){cout<<"STUDENT"<<endl;}
protected:
    char *num;
};
 
int main()
{
    {
    STUDENT st("zhsangsan",'x',"100");
    st.display();
    }
 
    cout<<"****************"<<endl;
 
    PERSON *p = new STUDENT("zhsangsan",'x',"100");
    p->display();
    delete p;
 
    return 0;
}

 结果为:

The name is zhsangsan
The sex is x
The num is 100
STUDENT
PERSON
****************
The name is zhsangsan
The sex is x
The num is 100
PERSON

此时如果将析构函数声明为 virtual:

virtual ~PERSON(){cout<<"PERSON"<<endl;}

 结果为:

The name is zhsangsan
The sex is x
The num is 100
STUDENT
PERSON
****************
The name is zhsangsan
The sex is x
The num is 100
STUDENT
PERSON

可以看出,对于堆对象来说,含有虚函数的类对象析构与栈对象析构是有所差别的。为了防止这种情况出现,最好是将含有虚函数的析构函数声明为 virtual。

注意事项

  • 因为虚函数是用在继承中的,因此只有类成员函数才能声明为虚函数
  • 静态成员函数不能是虚函数
  • 内联函数不能是虚函数
  • 构造函数不能是虚函数
  • 析构函数可以是虚函数且通常声明为虚函数

RTTI

(Run Time Type Identification,RTTI) 也叫运行时类型信息,也是通过多态实现的。

typeid

typeid 返回包含操作数数据类型信息的 type_info 对象的一个引用,信息中包括数据类型的名称。要使用 typeid,需要在函数中包含:

#include <typeinfo>
  • type_info 重载了操作符 ==,!= 用来进行比较
  • 函数 name() 返回类型名称
  • type_info 的拷贝和赋值都是私有的,因此不可拷贝和赋值
#include <iostream>
#include <typeinfo>
 
using namespace std;
 
typedef void (*Func)();
 
class Base1
{
};
 
class Base2
{
public:
    virtual ~Base2(){}
};
 
class Derive1:public Base1
{
};
 
class Derive2:public Base2
{
};
 
int main()
{
    cout<<typeid(int).name()<<endl;
    cout<<typeid(double).name()<<endl;
    cout<<typeid(char *).name()<<endl;
    cout<<typeid(char **).name()<<endl;
    cout<<typeid(const char *).name()<<endl;
    cout<<typeid(const char * const ).name()<<endl;
    cout<<"********************"<<endl;
 
    cout<<typeid(Func).name()<<endl;
    cout<<typeid(Base1).name()<<endl;
    cout<<typeid(Base2).name()<<endl;
    cout<<typeid(Derive1).name()<<endl;
    cout<<typeid(Derive2).name()<<endl;
    cout<<"********************"<<endl;
 
    Derive1 d;
    Base1 &b = d;
    cout<<typeid(b).name()<<endl;
    cout<<typeid(d).name()<<endl;
    cout<<"********************"<<endl;
 
    Derive2 dd;
    Base2 &bb = dd;
    cout<<typeid(bb).name()<<endl;
    cout<<typeid(dd).name()<<endl;
    cout<<"********************"<<endl;
 
    Base1 *p = &d;
    cout<<typeid(p).name()<<endl;
    cout<<typeid(*p).name()<<endl;
    cout<<typeid(d).name()<<endl;
    cout<<boolalpha<<(typeid(*p)== typeid(d))<<endl;
    cout<<"********************"<<endl;
 
    Base2 *pp = &dd;
    cout<<typeid(pp).name()<<endl;
    cout<<typeid(*pp).name()<<endl;
    cout<<typeid(dd).name()<<endl;
    cout<<boolalpha<<(typeid(*pp)== typeid(dd))<<endl;
    cout<<"********************"<<endl;
 
    return 0;
}

结果为:

i
d
Pc
PPc
PKc
PKc
********************
PFvvE
5Base1
5Base2
7Derive1
7Derive2
********************
5Base1
7Derive1
********************
7Derive2
7Derive2
********************
P5Base1
5Base1
7Derive1
false
********************
P5Base2
7Derive2
7Derive2
true
********************

从上边可以看出,在 typeid 涉及到虚函数时,利用指针得到的结果就可能出现差别,因此在使用 typeid 时需要注意:

  • 确保基类中至少定义了一个虚函数(虚析构也可)
  • 在涉及到虚函数时,尽量不要将 typeid 应用于指针,而是应用于引用,或者解引用的指针
  • typeid 是一个运算符,而不是函数
  • typeid 运算符返回的 type_info 类型,其拷贝构造函数和赋值运算函数都声明为 private,因此不能用于 stl 容器。也因此我们一般不直接保存 type_info,而是保存 type_info 的 name 信息

Notice how the type that typeid considers for pointers is the pointer type itself(both a and b are of type class Base *). However, when typeid is applied to objects(like *a and *b) typeid yields their dynamic type (i.e. the type of their most derived complete object).

If the type typeid evaluates is a pointer preceded by the dereference operator (*), and this pointer has a null value, typeid throws a bad_typeid exception.

typecast

在之前的文章中,我们简单介绍过 static_cast,reininterpreter_cast,const_cast 的用法,当时还剩下一个 dynamic_cast。

dynamic_cast 是一种运行时的类型转换方式,因此用于运行时的转换判断。该转换能够检查指针所指向的类型,然后判断这一类型与转换的目标类型是否相同,如果是返回对象地址,如果不是返回 NULL。

dynamic_cast 常用于多态继承中,来判断父类指针的真实指向。

#include <iostream>
#include <typeinfo>
 
using namespace std;
 
class A
{
public:
    virtual ~A(){}
};
 
class B:public A
{
};
 
class C:public A
{
};
 
class D
{
};
 
int main()
{
    B b;
    A *pa = &b;
 
    B *pb = dynamic_cast<B*>(pa); //成功
    cout<<pb<<endl;
 
    C *pc = dynamic_cast<C*>(pa); //成功 安全
    cout<<pc<<endl;
 
    D *pd = dynamic_cast<D*>(pa); //成功 安全
    cout<<pd<<endl;
 
    pb = static_cast<B*>(pa); //成功
    cout<<pb<<endl;
 
    pc = static_cast<C*>(pa); //成功 不安全
    cout<<pc<<endl;
 
    pb = reinterpret_cast<B*>(pa); //成功 不安全
    cout<<pb<<endl;
 
    pc = reinterpret_cast<C*>(pa); //成功 不安全
    cout<<pc<<endl;
 
    pd = reinterpret_cast<D*>(pa); //成功 不安全
    cout<<pd<<endl;
 
    return 0;
}

结果为:

0x61fe8c
0
0
0x61fe8c
0x61fe8c
0x61fe8c
0x61fe8c
0x61fe8c

在上述几种类型转换中,dynamic_cast 的转换用法算是比较安全的,因为这种转换方式是先比较再返回的,而 reininterpreter_cast 则是最不安全的,因为这种转换方式不做类型检查直接将源类型重新解释为目标类型,容易出错。

但 dynamic_cast 的目标类型必须是类的指针或者引用。

多态实现

虚函数

之前介绍函数重载,也就是静多态是通过 name mangling 实现的,而 C++ 的动多态则是通过虚函数表(virtual table)实现的。这个表中主要是一个类的虚函数的地址表,这张表包含了继承,override 的情况。在实际使用中,在含有虚函数的类对象中,该表会被分配到该对象的内存中,用于指明实际所要调用的函数。

C++ 编译器保证虚函数表的指针存在于实例对象的最前面,这表示实例对象的地址就是该虚函数表的位置,然后就可以遍历其中的函数指针,进行调用。

#include <iostream>
#include <typeinfo>
 
using namespace std;
 
class Base
{
public:
    void f() { cout << "Base::f" << endl; }
    void g() { cout << "Base::g" << endl; }
    void h() { cout << "Base::h" << endl; }
private:
    int data;
};
 
int main()
{
    Base b;
    cout<<"sizeof(Base) = "<<sizeof(Base)<<endl;
    cout<<"sizeof(b) = "<<sizeof(b)<<endl;
 
    return 0;
}

结果为:

sizeof(Base) = 4
sizeof(b) = 4

如果基类中存在虚函数,则为:

#include <iostream>
#include <typeinfo>
 
using namespace std;
 
class Base
{
public:
    virtual void f() { cout << "Base::f" << endl; }
    virtual void g() { cout << "Base::g" << endl; }
    virtual void h() { cout << "Base::h" << endl; }
private:
    int data;
};
 
int main()
{
    Base b;
    cout<<"sizeof(Base) = "<<sizeof(Base)<<endl;
    cout<<"sizeof(b) = "<<sizeof(b)<<endl;
 
    return 0;
}

结果为:

sizeof(Base) = 8
sizeof(b) = 8

可以看出有虚函数的基类的大小会比没有虚函数的基类大小多出一个指针的大小。这个多出来的指针就是虚函数表的位置。

#include <iostream>
#include <typeinfo>
 
using namespace std;
 
class Base
{
public:
    virtual void f() { cout << "Base::f" << endl; }
    virtual void g() { cout << "Base::g" << endl; }
    virtual void h() { cout << "Base::h" << endl; }
private:
    int data;
};
 
typedef void (*FUNC)(void);
 
int main()
{
    Base b;
    cout<<"sizeof(Base) = "<<sizeof(Base)<<endl;
    cout<<"sizeof(b) = "<<sizeof(b)<<endl;
 
    cout<<&b<<endl;
    cout<<*((int **)*(int *)(&b)+0)<<endl;
    cout<<*((int **)*(int *)(&b)+1)<<endl;
    cout<<*((int **)*(int *)(&b)+2)<<endl;
    cout<<*((int **)*(int *)(&b)+3)<<endl;
 
    FUNC pf = NULL;
    pf = (FUNC)*((int **)*(int *)(&b)+0);
    pf();
    pf = (FUNC)*((int **)*(int *)(&b)+1);
    pf();
    pf = (FUNC)*((int **)*(int *)(&b)+2);
    pf();
 
    return 0;
}

结果为:

sizeof(Base) = 8
sizeof(b) = 8
0x61fe94
0x4029f0
0x402a24
0x402a58
0x3a434347
Base::f
Base::g
Base::h

上面的程序中:

  • 先将 &b 转换为 int *(这样能够保证 +1 一次增加一个指针的大小),取得虚函数表的地址
  • 然后,再次取址就得到了第一个虚函数的地址,也就是 Base::f
  • 最后再转换为 int **,通过 +1,+2 后取址,就能够得到 Base::g,Base::h

一般继承(no override)

#include <iostream>
#include <typeinfo>
 
using namespace std;
 
class Base
{
public:
    virtual void f() { cout << "Base::f" << endl; }
    virtual void g() { cout << "Base::g" << endl; }
    virtual void h() { cout << "Base::h" << endl; }
private:
    int data;
};
 
class Derive:public Base
{
    virtual void f1() { cout << "Base::f1" << endl; }
    virtual void g1() { cout << "Base::g1" << endl; }
    virtual void h1() { cout << "Base::h1" << endl; }
};
 
typedef void (*FUNC)(void);
 
int main()
{
    Derive b;
    cout<<"sizeof(Base) = "<<sizeof(Base)<<endl;
    cout<<"sizeof(Derive) = "<<sizeof(Derive)<<endl;
    cout<<"sizeof(b) = "<<sizeof(b)<<endl;
 
    cout<<&b<<endl;
    cout<<*((int **)*(int *)(&b)+0)<<endl;
    cout<<*((int **)*(int *)(&b)+1)<<endl;
    cout<<*((int **)*(int *)(&b)+2)<<endl;
    cout<<*((int **)*(int *)(&b)+3)<<endl;
    cout<<*((int **)*(int *)(&b)+4)<<endl;
    cout<<*((int **)*(int *)(&b)+5)<<endl;
    cout<<*((int **)*(int *)(&b)+6)<<endl;
 
    FUNC pf = NULL;
    pf = (FUNC)*((int **)*(int *)(&b)+0);
    pf();
    pf = (FUNC)*((int **)*(int *)(&b)+1);
    pf();
    pf = (FUNC)*((int **)*(int *)(&b)+2);
    pf();
    pf = (FUNC)*((int **)*(int *)(&b)+3);
    pf();
    pf = (FUNC)*((int **)*(int *)(&b)+4);
    pf();
    pf = (FUNC)*((int **)*(int *)(&b)+5);
    pf();
 
    return 0;
}

结果为:

sizeof(Base) = 8
sizeof(Derive) = 8
sizeof(b) = 8
0x61fe94
0x402ae0
0x402b14
0x402b48
0x402b94
0x402bc8
0x402bfc
0x3a434347
Base::f
Base::g
Base::h
Base::f1
Base::g1
Base::h1

在上边的例子中,派生类没有 override 任何父类的函数,并又重新定义了几个虚函数,因此对于派生类来说:

  • 虚函数按照其声明顺序在表中存放
  • 父类的虚函数在子类的虚函数前边

一般继承(override)

#include <iostream>
#include <typeinfo>
 
using namespace std;
 
class Base
{
public:
    virtual void f() { cout << "Base::f" << endl; }
    virtual void g() { cout << "Base::g" << endl; }
    virtual void h() { cout << "Base::h" << endl; }
private:
    int data;
};
 
class Derive:public Base
{
    virtual void f() { cout << "Base::f1" << endl; }
    virtual void g1() { cout << "Base::g1" << endl; }
    virtual void h1() { cout << "Base::h1" << endl; }
};
 
typedef void (*FUNC)(void);
 
int main()
{
    Derive b;
    cout<<"sizeof(Base) = "<<sizeof(Base)<<endl;
    cout<<"sizeof(Derive) = "<<sizeof(Derive)<<endl;
    cout<<"sizeof(b) = "<<sizeof(b)<<endl;
 
    cout<<&b<<endl;
    cout<<*((int **)*(int *)(&b)+0)<<endl;
    cout<<*((int **)*(int *)(&b)+1)<<endl;
    cout<<*((int **)*(int *)(&b)+2)<<endl;
    cout<<*((int **)*(int *)(&b)+3)<<endl;
    cout<<*((int **)*(int *)(&b)+4)<<endl;
    cout<<*((int **)*(int *)(&b)+5)<<endl;
 
    FUNC pf = NULL;
    pf = (FUNC)*((int **)*(int *)(&b)+0);
    pf();
    pf = (FUNC)*((int **)*(int *)(&b)+1);
    pf();
    pf = (FUNC)*((int **)*(int *)(&b)+2);
    pf();
    pf = (FUNC)*((int **)*(int *)(&b)+3);
    pf();
    pf = (FUNC)*((int **)*(int *)(&b)+4);
    pf();
 
    return 0;
}

结果为:

sizeof(Base) = 8
sizeof(Derive) = 8
sizeof(b) = 8
0x61fe94
0x402b54
0x402ad4
0x402b08
0x402b88
0x402bbc
0x3a434347
Base::f1
Base::g
Base::h
Base::g1
Base::h1

在上边的例子中,派生类 override 了父类的 f 函数,并又重新定义了几个虚函数,因此对于派生类来说:

  • override 的 f 函数被放到了虚函数表中原来基类虚函数的位置
  • 没有 override 的函数不变

过程推断

Base *b = new Derive();
b->f();

这段代码的实际过程为:

  • 明确 b 类型
  • 通过指向虚函数表的指针和偏移量,来匹配虚函数的地址
  • 根据地址调用虚函数

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: C++中关于多态实现和使用方法

本文链接: https://www.lsjlt.com/news/165119.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++中关于多态实现和使用方法
    目录赋值兼容实例多态静多态动多态格式实例override纯虚函数含有虚函数的析构函数注意事项RTTItypeidtypecast多态实现虚函数一般继承(no override)一般继...
    99+
    2024-04-02
  • 关于Object.entries()方法的使用和实现方式
    Object.entries()方法的使用和实现 1、定义 Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该...
    99+
    2023-02-10
    Object.entries()方法 使用Object.entries() Object.entries()
  • 实现Golang中多态性的方法和用途
    Golang中如何利用接口实现多态性在Golang中,接口是一种强大的特性,可以实现多态性,即一个对象可以以不同的形态呈现。利用接口实现多态性能够提高代码的可扩展性和可维护性。本文将通过介绍接口的定义、接口的实现和多态性的实例,来阐述在Go...
    99+
    2023-12-29
    接口 Golang 多态性
  • C++关于指针,继承和多态介绍
    目录指针指针和继承指针、继承和多态指针 我们在书本上学到的指针基本上都是:首先,指针是一个变量;其次,这个变量存储的值是一个地址。这个是对指针的一个基本理解,最近在编程中发现了一些新...
    99+
    2024-04-02
  • C/C++使用C语言实现多态
    目录1.多态的概念1.1什么是多态?1.2为什么要用多态呢?1.3多态有什么好处?2.多态的定义及实现2.1继承中构成多态的条件2.2虚函数2.3虚函数的重写2.4C++11 ove...
    99+
    2024-04-02
  • c++多态实现的方法有哪些
    C++中实现多态的方法有以下几种:1. 虚函数(Virtual Functions):在基类中声明一个虚函数,在派生类中可以对该函数...
    99+
    2023-10-12
    c++
  • JS中关于Class类的静态属性和静态方法
    目录一、类的两个概念二、对象的两个部分1、属性 2、方法三、静态方法使用:在方法前加上static关键字1、为什么使用静态方法三、总结1、静态属性和非静态属性的区别2.使用...
    99+
    2022-11-13
    JS中Class类 Class类静态属性 Class类静态方法
  • C/C++关于实现CAN信号的获取方法
    目录CAN基础知识CAN 信号C语言涉及到知识CAN基础知识 标准的CAN 数据为8字节,即64位,但是CAN FD的最大数据可为64字节,为512位,其中的帧ID分为标准帧和扩展帧...
    99+
    2023-02-03
    C++ CAN信号 C++ CAN信号获取 C语言CAN信号
  • C#中多态性学习/虚方法/抽象方法和接口怎么使用
    这篇文章主要介绍了C#中多态性学习/虚方法/抽象方法和接口怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C#中多态性学习/虚方法/抽象方法和接口怎么使用文章都会有所收获,下面我们一起来看看吧。1. 多态...
    99+
    2023-07-05
  • 实现Golang多态的方法和技巧
    Golang多态的实现方法和技巧 在Go语言中,多态是一种实现面向对象编程的重要概念,它可以让不同类型的对象以相同的方式被使用。通过使用多态,可以减少代码的冗余,增加代码的灵活性和可扩展性。本文将介绍Gola...
    99+
    2024-01-29
    技巧 实现方法 Golang多态
  • C++多态实现方式详情
    注:文章转自公众号:Coder梁(ID:Coder_LT) 在我们之前介绍的继承的情况当中,派生类调用基类的方法都是不做任何改动的调用。 但有的时候会有一些特殊的情况,我们会希望同一...
    99+
    2024-04-02
  • C++中怎么实现多态
    C++中怎么实现多态,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。实现了C++多态 2 5 1 6#include < iostream>&nb...
    99+
    2023-06-17
  • Scala方法的嵌套和方法多态怎么实现
    本篇内容主要讲解“Scala方法的嵌套和方法多态怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Scala方法的嵌套和方法多态怎么实现”吧!方法里嵌套定义其他方法示例1object&nbs...
    99+
    2023-06-02
  • 关于@Autowired注解和静态方法及new的关系
    目录@Autowired注解和静态方法及new关系一、@autowired 与new 二、@autowired 与静态方法1.spring框架应用中有些静态方法需要依赖被容...
    99+
    2024-04-02
  • C++中的多态如何实现
    这篇文章主要介绍“C++中的多态如何实现”,在日常操作中,相信很多人在C++中的多态如何实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++中的多态如何实现”的疑惑有所帮助!接下来,请跟着小编一起来学习吧...
    99+
    2023-06-30
  • C#中怎么实现多态性
    在C#中实现多态性一般通过继承和接口实现。具体方法如下: 继承:通过创建一个父类和多个子类,子类继承父类的特性,并且可以重写父类的...
    99+
    2024-03-06
    C#
  • C#中关于double.ToString()的用法
    目录C# double.ToString()的用法下面列出几个常用的方法C# Double 按有效数字 ToString将double转换为n有效数字的字符所以就写了一个函数总结C#...
    99+
    2023-02-26
    C# double.ToString() double.ToString()用法 double.ToString()
  • C#中如何使用静态方法
    C#中如何使用静态方法,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。C#静态方法使用中遇到的问题:在源码工程中几乎没有看到什么静态方法,但是在Ms的SQLHelper中几乎全部...
    99+
    2023-06-17
  • C++中多态性实现的问题与解决方法概述
    C++中多态性实现的问题与解决方法概述引言:在C++中,多态性是一种重要的特性,它允许我们在编译时不确定某个对象的真正类型,而在运行时根据实际的类型进行相应的操作。然而,实现多态性也会面临一些问题,本文将简要介绍这些问题,并提供一些解决方法...
    99+
    2023-10-22
    问题 实现 解决方法 多态性 关键词:C++
  • C++中多态性实现问题及解决方法的讨论
    C++中多态性实现问题及解决方法的讨论多态性是C++语言中一项非常重要的特性,它使得一个类的对象可以根据其具体类型表现出不同的行为。然而,在实际的应用中,我们有时会遇到一些问题,特别是在多继承和虚析构函数的使用场景下。一、多态性的实现在C+...
    99+
    2023-10-22
    多态性 (Polymorphism) C++编程 (C++ programming) 实现问题 (Implementat
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作