目录

一、 using声明符

二、using在类定义中

三、 using引起的函数覆盖或隐藏

四、using 引入基类构造函数的风险

五、using在多继承下的冲突问题

六、using 变更访问权限

七、using 声明与模板参数

八、using 声明与枚举项

九、using 声明与操作符问题

十、源码补充


一、 using声明符

using 声明,将别处定义的名字引入到此 using 声明所出现的声明区中,其语法形式如下:

/*
*typename-在using声明从基类向类模板中引入成员类型时,可能需要用关键词typename解决待决名
*嵌套名说明符-名字与作用域解析运算符::的序列,以作用域解析运算符结尾。单个::指代全局命名空间。
*无限定标识-标识表达式
*/
using typename(可选) 嵌套名说明符 无限定标识; //(C++17 前)
/*
*声明符列表-一个或多个形式为typename(可选) 嵌套名说明符无限定标识的声明符的逗号分隔列表。某些或所
*有声明符都可以后随省略号 ... 以指示包展开
*/
using 声明符列表;                            //(C++17 起)

using 声明可以用于将命名空间成员引入到另一命名空间与块作用域,或将基类成员引入到派生类定义中,或将枚举项引入命名空间、块或类作用域中 (C++20 起)。包含多于一个 using 声明符的 using 声明等价于一个对应个数的包含单个 using 声明符的 using 声明序列。 (C++17 起)

例如在派生类通过using引入基类构造函数,不继承默认实参,其签名与基类中的构造函数命名相匹配的构造函数(包括隐式的)候选继承,在派生类中隐式声明。

struct B {B(int = 13, int = 42);
};
struct D : B {using B::B;
// 继承构造函数候选集是
// 1. B(const B&)
// 2. B(B&&)
// 3. B(int = 13, int = 42)
// 4. B(int = 13)
// 5. B()// D 有下列构造函数:
// 1. D()
// 2. D(const D&)
// 3. D(D&&)
// 4. D(int, int) <- 继承的
// 5. D(int) <- 继承的
};

二、using在类定义中

using 声明可以将基类成员引入到派生类的定义中,例如将基类的受保护成员暴露为派生类的公开成员。此时嵌套名说明符必须指名所定义的类的某个基类。如果这个名字是该基类的某个重载的成员函数的名字,那么具有该名字的所有基类成员函数均被引入。

class A_US
{
public:A_US(int i){std::cout << "A_US(int)\n";}A_US(double d, int i){std::cout << "A_US(double,int)\n";}A_US(float f, int i, const char* c){std::cout << "A_US(float,int,char*)\n";}
};class B_US:A_US
{
public:virtual void Extralnterface(){} //扩展接口
};class C_US:A_US
{
public://接口透传,实现父类构造函数集C_US(int i):A_US(i){std::cout << "C_US(int)\n";}C_US(double d, int i):A_US(d, i){std::cout << "C_US(double,int)\n";}C_US(float f, int i, const char* c): A_US(f, i, c){std::cout << "C_US(float,int,char*)\n";}// ... virtual void Extralnterface(){} //扩展接口
};class D_US:A_US
{
public:using A_US::A_US;virtual void Extralnterface(){} //扩展接口
};void using_test(void)
{// B_US bu1(10);           //无匹配构造函数// B_US bu2(1.0,1);        //无匹配构造函数// B_US bu3(1.0,1,nullptr);//无匹配构造函数C_US cu1(10);C_US cu2(1.0,1);C_US cu3(1.0,1,nullptr);D_US du1(10);           D_US du2(1.0,1);D_US du3(1.0,1,nullptr);
}
//out log
A_US(int)
C_US(int)
A_US(double,int)
C_US(double,int)
A_US(float,int,char*)
C_US(float,int,char*)
A_US(int)
A_US(double,int)
A_US(float,int,char*)

在上述代码中,派生类型只是想扩展一个接口,其他地方保持不变,B_US类型没有重新定义各种构造函数,实现不了各种对象创建方法;C_US费心费力定义了和基类A_US一致的构造函数,但是做了很多重复性工作;而类型D_US通过using引入基类的构造函数,直接省事省力和C_US一样的实现了基类构造。

三、 using引起的函数覆盖或隐藏

如果派生类已包含具有相同名字、形参列表和限定的成员,那么派生类成员隐藏或覆盖从基类引入的成员(不与之冲突)。

class A {
public:virtual void f(int) { std::cout << "A::f\n"; }void g(char)        { std::cout << "A::g\n"; }void h(int)         { std::cout << "A::h\n"; }protected:int m; // A::m 是受保护的typedef int value_type;
};class B : public A {
public:using A::m; // B::m 是公开的using A::value_type; // B::value_type 是公开的using A::f;void f(int) { std::cout << "B::f\n"; } // B::f(int) 覆盖 A::f(int)using A::g;void g(int) { std::cout << "B::g\n"; } // g(int) 与 g(char) 均作为 B 成员可见using A::h;void h(int) { std::cout << "B::h\n"; } // B::h(int) 隐藏 A::h(int)
};
void using_test(void)
{B b;A& a = b;// b.m = 2;// 错误,A::m 受保护b.m = 1;   // 受保护的 A::m 可作为公开的 B::m 访问a.f(1);    // 调用派生类 f()b.f(1);    // 调用派生类 f()b.g(1);    // 调用派生类 g(int)b.g('a');  // 调用基类 g(char)a.h(1);    // 调用基类 h()b.h(1);    // 调用派生类 h()
}
//out log
B::f
B::f
B::g
A::g
A::h
B::h

上述代码中在派生类的函数g和基类的函数g是形参类型不同的,因此不会被覆盖,支持到两个g函数版本。而对于f函数,派生类会覆盖基类的虚函数,对于h函数,派生类会隐藏基类的普通函数。

四、using 引入基类构造函数的风险

如果 using 声明指代了正在定义的类的某个直接基类的构造函数(using Base::Base;),那么在初始化派生类时,该基类的所有构造函数(忽略成员访问)均对重载决议可见。如果重载决议选择了继承的构造函数,那么如果它被用于构造相应基类的对象时可访问,它也是可访问的:引入它的 using 声明的可访问性被忽略。

如果在初始化这种派生类对象时重载决议选择了继承的构造函数之一,那么用这个继承的构造函数对从之继承该构造函数的 Base 子对象进行初始化,而 Derived 的所有其他基类和成员,都如同以预置的默认构造函数一样进行初始化(如果提供默认成员初始化器则使用,否则进行默认初始化)。整个初始化被视作单个函数调用:继承的构造函数的各形参的初始化,按顺序早于派生类对象的任何基类或成员的初始化。

class A_US
{
public:A_US(int i){std::cout << "A_US(int)\n";}A_US(double d, int i){std::cout << "A_US(double,int)\n";}A_US(float f, int i, const char* c){std::cout << "A_US(float,int,char*)\n";}
};class E_US:A_US
{
public:using A_US::A_US;
private:int ival;double dval;
};
//
void using_test(void)
{// E_US eu;                //错误没有默认构造E_US eu1(10);           //OK,调用A_US的,ival、dval被默认初始化(不进行初始化)E_US eu2(1.0,1);        //OK,调用A_US的,ival、dval被默认初始化(不进行初始化)E_US eu3(1.0,1,nullptr);//OK,调用A_US的,ival、dval被默认初始化(不进行初始化)
}

如果派生类中的成员变量没有提供默认初始化,采用using引入基类的构造函数可能会导致错误。

class A_US
{
public:A_US(int i){std::cout << "A_US(int)\n";}A_US(double d, int i){std::cout << "A_US(double,int)\n";}A_US(float f, int i, const char* c){std::cout << "A_US(float,int,char*)\n";}
};class USTest
{
public:USTest(int){};
};
class F_US:A_US
{
public:using A_US::A_US;
private:USTest ut;
};
//// F_US fu1(10);           //error,USTest无默认初始化导致错误// F_US fu2(1.0,1);        //error,USTest无默认初始化导致错误// F_US fu3(1.0,1,nullptr);//error,USTest无默认初始化导致错误

这是因为通过using引入继承了基类的构造函数,只是对基类成员变量进行了初始化,为对于派生类本身的成员变量没有处理,只能寄望于成员变量本身提供默认初始化能力,否则就会出错。

五、using在多继承下的冲突问题

如果构造函数多个基类子对象继承,那么程序非良构,这与多继承的非静态成员函数相似。通过using引入基类的成员函数,需要注意多继承下的冲突问题:

class A1
{
public:A1(int){};
};
class A2
{
public:A2(int){};
};
//展示一
class B12 : public A1,A2
{
public:using A1::A1;using A2::A2;   //冲突
};
B12 b12(10);    //error
//展示二
class B12 : public A1,A2
{
public:using A1::A1;//using A2::A2;
};
B12 b12(10);    //采用A1构造
//展示三
class B12 : public A1, public A2
{
public:using A1::A1;using A2::A2;B12(int){};    //error: no matching function for call to 'A1::A1' and 'A2::A2()'
};
B12 b12(10);    //
//展现四
class A1
{
public:A1(){};    //支持默认构造A1(int){};
};
class A2
{
public:A2(){};    //支持默认构造A2(int){};
};
//与任何其他非静态成员函数的 using 声明相同,如果继承的构造函数的签名与 Derived 的构造函数之一匹配,那么它被 Derived 中找到的版本从查找中隐藏。
//如果 Base 的继承构造函数恰好有与 Derived 的复制/移动构造函数匹配的签名,那么它不妨碍 Derived 复制/移动构造函数的隐式生成(然后继承的版本被其隐藏,这与 using operator= 类似)。
class B12 : public A1, public A2
{
public:using A1::A1;//不生效,基类初始调用默认构造using A2::A2;//不生效,基类初始调用默认构造B12(int){};
};
B12 b12(10);    //OK,采用B12构造

通过虚继承、显式禁用、访问授权等多种组合形式防止冲突发生。

class W_US { public: W_US(int){}; };
class X_US : virtual public W_US {
public:using W_US::W_US;   // 继承 W_US(int)X_US() = delete;    //默认构造强制删除
};class Y_US : public X_US {
public:using X_US::X_US;
};class K_US : public W_US {
public:K_US():W_US(0){};   //默认构造
private:using W_US::W_US;   // 继承 W_US(int),隐藏
};class Z_US : public Y_US, public K_US, virtual public W_US {
public:using Y_US::Y_US;
};
//
Z_US zus(0); // OK:Y_US 的初始化不调用 X_US 的默认构造函数

虚继承对于using引入基类函数引起的冲突规避同样有效:

class AU { public:AU(int){}; };
class BU : public AU { public:using AU::AU; };
class CU1 : public BU { public:using BU::BU; };
class CU2 : public BU { public:using BU::BU; };class DU1 : public CU1, CU2 {
public:using CU1::CU1;using CU2::CU2;
};class VU1 : virtual BU { public:using BU::BU; };
class VU2 : virtual BU { public:using BU::BU; };class DU2 : public VU1, VU2 {
public:using VU1::VU1;using VU2::VU2;
};
//// DU1 d1(0); // error,非良构:从不同的 B 基类子对象继承的构造函数/**OK:只有一个 B 子对象。*这初始化虚 B 基类,它初始化 A 基类*然后如同用预置的默认构造函数*初始化 V1 与 V2 基类*/DU2 d2(0); // 

六、using 变更访问权限

using 声明可以将基类成员引入到派生类的定义中,例如将基类的受保护成员暴露为派生类的公开成员。

class A3
{
protected:  //保护函数void f(int){std::cout <<"A3::f(int)\n";};int ival;
};
class B3 : public A3
{
public:using A3::f;    //转换为公有函数using A3::ival;
private:
};class C3 : private B3   //私有继承
{
public:using B3::f;        //公有函数
private:using B3::ival;     //转为私有
};
//B3 b3;b3.ival = 10;//b3.f(10);    //C3 c3;//c3.ival = 10;//errorc3.f(10);   //可外部调用

七、using 声明与模板参数

在模板化类中,如果 using 声明指代待决名(模板参数),而嵌套名说明符拥有与该无限定标识 相同的终止名,那么认为它指名构造函数。当采用实参传递时,模板参数类型明确,这是在创建该特例实现时,就会触发冲突问题。

using 声明不能指代命名空间,有作用域枚举项 (C++20 前),基类的析构函数,或用户定义转换函数的成员模板的特化,也不能using 声明指名成员模板的特化(语法不容许模板标识)。

class USTest
{
public:USTest(int){std::cout<<"USTest(int)\n";};
};template<class T>
class AT : public T {
public:using T::T; // OK :继承 T 的构造函数template<typename U> void f(U){};
private:char cval;
};template<class T, class U>
class BT : public T, AT<U> {
public:using typename AT<U>::AT; // OK :继承 AT<U> 的构造函数// using typename AT<int>::AT; // error,不能引入特例化using typename T::T;      // 继承 T 的构造函数using typename AT<U>::f;  //using typename AT<T>::f;  //// using typename AT<int>::f;  //error,不能引入特例化void g() {// f<int>(0);       // 错误:已知 f 不是目标名,// 因此 < 不开始模板实参列表f(0);   // OK}
private:int ival;
};template<class T>
class CT : public T, AT<T> {
public:using AT<T>::AT; // OK :继承 AT<T> 的构造函数,而AT<T> 继承T的构造函数// using typename AT<int>::AT; // error :不能引入特例化using T::T;      // 同样继承 T 的构造函数
private:int ival;
};
//AT<int> at();           //warning: empty parentheses were disambiguated as a function declaration [-Wvexing-parse]BT<int,float> bt();     //warning: empty parentheses were disambiguated as a function declaration [-Wvexing-parse]CT<int> ct();           //warning: empty parentheses were disambiguated as a function declaration [-Wvexing-parse]//AT<USTest> at1();       //warning: empty parentheses were disambiguated as a function declaration [-Wvexing-parse]BT<USTest,float> bt1(); //warning: empty parentheses were disambiguated as a function declaration [-Wvexing-parse]CT<USTest> ct1();       //warning: empty parentheses were disambiguated as a function declaration [-Wvexing-parse]//AT<USTest> at2(1);      //OK// BT<USTest,USTest> bt2(1);  //error,多个构造冲突// BT<USTest,float> bt2(1);//error,base type 'float' fails to be a struct or class type float(int)// CT<USTest> ct2(1);  //error,多个构造冲突

八、using 声明与枚举项

C++20 起,using 声明也能将枚举的枚举项引入命名空间、块和类作用域。using 声明也能用于无作用域枚举项。using 声明枚举类型名时,并不传送其枚举项。

enum num { aval,bval };
using num::aval; // OK ,c++11
//以下c++20
enum class direction { east, west,north,south};
struct walk {using direction::east;direction e = east; // OK// direction n = north;// error,north并没有被using,使用时需要+作用域direction n = direction::north;
};using direction::north;
constexpr direction norw = north; // OKconstexpr auto get_dir(bool is_nor)
{using direction::north, direction::south;return is_nor ? north : south; // OK
}

九、using 声明与操作符问题

如果 using 声明引入基类的赋值运算符到派生类,而其签名恰好与派生类的复制赋值或移动赋值运算符匹配,那么该运算符被派生类的隐式声明的复制/移动赋值运算符隐藏。

class OP_US
{
protected:/* data */int ival;
public:OP_US& operator=(const OP_US& obj){std::cout << "OP_US operator=&\n";if(this==&obj) return *this;ival = obj.ival;return *this;};
};
class DOP_US1 : public OP_US
{
private:/* data */
public:using OP_US::operator=;
};
class DOP_US2 : public OP_US
{
private:/* data */
public:using OP_US::operator=;DOP_US2& operator=(const DOP_US2& obj){std::cout << "DOP_US2 operator=&\n";if(this==&obj) return *this;ival = obj.ival;return *this;};
};
class DOP_US3 : public OP_US
{
private:/* data */double dval;
public:using OP_US::operator=;DOP_US3& operator=(const DOP_US3&& obj){std::cout << "DOP_US3 operator= &&\n";ival = std::move(obj.ival);return *this;};
};
//DOP_US1 dop1,dop2;dop2 = dop1;    //OP_US operator=&DOP_US2 dop3,dop4;dop4 = dop3;    //OP_US2 operator=&DOP_US3 dop5,dop6;// dop6 = dop5;    //error: use of deleted function 'DOP_US3& DOP_US3::operator=(const DOP_US3&)'dop6 = std::move(dop5);//OP_US3 operator=&&

相同的规则适用于继承恰好与派生类的移动/复制构造函数匹配的基类构造函数的 using 声明(C++11 起)。

感谢读友能耐心看到最后,本人文章都很长,知识点很细,可能会有所遗漏和失误,如果有不妥之处,烦请指出。如果内容对您有所触动,请点赞关注一下防止不迷路。

十、源码补充

编译指令g++ main.cpp test*.cpp -o test.exe -std=c++11(或c++20).

main.cpp

#include "test1.h"int main(int argc, char* argv[])
{using_test();return 0;
}

test1.h

#ifndef _TEST_1_H_
#define _TEST_1_H_void using_test(void);#endif //_TEST_1_H_

test1.cpp

#include "test1.h"#include <iostream>
#include <stdexcept>class A {
public:virtual void f(int) { std::cout << "A::f\n"; }void g(char)        { std::cout << "A::g\n"; }void h(int)         { std::cout << "A::h\n"; }protected:int m; // A::m 是受保护的typedef int value_type;
};class B : public A {
public:using A::m; // B::m 是公开的using A::value_type; // B::value_type 是公开的using A::f;void f(int) { std::cout << "B::f\n"; } // B::f(int) 覆盖 A::f(int)using A::g;void g(int) { std::cout << "B::g\n"; } // g(int) 与 g(char) 均作为 B 成员可见using A::h;void h(int) { std::cout << "B::h\n"; } // B::h(int) 隐藏 A::h(int)
};class A_US
{
public:A_US(int i){std::cout << "A_US(int)\n";}A_US(double d, int i){std::cout << "A_US(double,int)\n";}A_US(float f, int i, const char* c){std::cout << "A_US(float,int,char*)\n";}
};class B_US:A_US
{
public:virtual void Extralnterface(){} //扩展接口
};class C_US:A_US
{
public://接口透传,实现父类构造函数集C_US(int i):A_US(i){std::cout << "C_US(int)\n";}C_US(double d, int i):A_US(d, i){std::cout << "C_US(double,int)\n";}C_US(float f, int i, const char* c): A_US(f, i, c){std::cout << "C_US(float,int,char*)\n";}// ... virtual void Extralnterface(){} //扩展接口
};class D_US:A_US
{
public:using A_US::A_US;virtual void Extralnterface(){} //扩展接口
};class E_US:A_US
{
public:using A_US::A_US;
private:int ival;double dval;
};class USTest
{
public:USTest(int){std::cout<<"USTest(int)\n";};
};
class F_US:A_US
{
public:using A_US::A_US;
private:USTest ut;
};class A1
{
public:A1(){};A1(int){};
};
class A2
{
public:A2(){};A2(int){};
};class B12 : public A1, public A2
{
public:using A1::A1;using A2::A2;B12(int){};
};class W_US { public: W_US(int){}; };
class X_US : virtual public W_US {
public:using W_US::W_US;   // 继承 W_US(int)X_US() = delete;
};class Y_US : public X_US {
public:using X_US::X_US;
};class K_US : public W_US {
public:K_US():W_US(0){};
private:using W_US::W_US;   // 继承 W_US(int),隐藏
};class Z_US : public Y_US, public K_US, virtual public W_US {
public:using Y_US::Y_US;
};class AU { public:AU(int){}; };
class BU : public AU { public:using AU::AU; };
class CU1 : public BU { public:using BU::BU; };
class CU2 : public BU { public:using BU::BU; };class DU1 : public CU1, CU2 {
public:using CU1::CU1;using CU2::CU2;
};class VU1 : virtual BU { public:using BU::BU; };
class VU2 : virtual BU { public:using BU::BU; };class DU2 : public VU1, VU2 {
public:using VU1::VU1;using VU2::VU2;
};class A3
{
protected:  //保护函数void f(int){std::cout <<"A3::f(int)\n";};int ival;
};
class B3 : public A3
{
public:using A3::f;    //转换为公有函数using A3::ival;
private:
};class C3 : private B3   //私有继承
{
public:using B3::f;        //公有函数
private:using B3::ival;     //转为私有
};template<class T>
class AT : public T {
public:using T::T; // OK :继承 T 的构造函数template<typename U> void f(U){};
private:char cval;
};template<class T, class U>
class BT : public T, AT<U> {
public:using typename AT<U>::AT; // OK :继承 AT<U> 的构造函数// using typename AT<int>::AT; // error,不能引入特例化using typename T::T;      // 继承 T 的构造函数using typename AT<U>::f;  //能编译,但 f 不是模板名using typename AT<T>::f;  //能编译,但 f 不是模板名// using typename AT<int>::f;  //error,不能引入特例化void g() {// f<int>(0);       // 错误:已知 f 不是目标名,// 因此 < 不开始模板实参列表f(0);   // OK}
private:int ival;
};template<class T>
class CT : public T, AT<T> {
public:using typename AT<T>::AT; // OK :继承 AT<U> 的构造函数// using typename AT<int>::AT; // error :不能引入特例化using typename T::T;      // 继承 T 的构造函数
private:int ival;
};enum num { aval,bval };
using num::aval; // OK ,c++11
#if __cplusplus > 201103L
//以下c++20
enum class direction { east, west,north,south};
struct walk {using direction::east;direction e = east; // OK// direction n = north;// error,north并没有被using,使用时需要+作用域direction n = direction::north;
};using direction::north;
constexpr direction norw = north; // OKconstexpr auto get_dir(bool is_nor)
{using direction::north, direction::south;return is_nor ? north : south; // OK
}
#endifclass OP_US
{
protected:/* data */int ival;
public:OP_US& operator=(const OP_US& obj){std::cout << "OP_US operator= &\n";if(this==&obj) return *this;ival = obj.ival;return *this;};
};
class DOP_US1 : public OP_US
{
private:/* data */
public:using OP_US::operator=;
};
class DOP_US2 : public OP_US
{
private:/* data */
public:using OP_US::operator=;DOP_US2& operator=(const DOP_US2& obj){std::cout << "DOP_US2 operator= &\n";if(this==&obj) return *this;ival = obj.ival;return *this;};
};
class DOP_US3 : public OP_US
{
private:/* data */double dval;
public:using OP_US::operator=;DOP_US3& operator=(const DOP_US3&& obj){std::cout << "DOP_US3 operator= &&\n";ival = std::move(obj.ival);return *this;};
};void using_test(void)
{B b;A& a = b;// b.m = 2;// 错误,A::m 受保护b.m = 1;   // 受保护的 A::m 可作为公开的 B::m 访问a.f(1);    // 调用派生类 f()b.f(1);    // 调用派生类 f()b.g(1);    // 调用派生类 g(int)b.g('a');  // 调用基类 g(char)a.h(1);    // 调用基类 h()b.h(1);    // 调用派生类 h()//// B_US bu1(10);           //无匹配构造函数// B_US bu2(1.0,1);        //无匹配构造函数// B_US bu3(1.0,1,nullptr);//无匹配构造函数C_US cu1(10);C_US cu2(1.0,1);C_US cu3(1.0,1,nullptr);D_US du1(10);           D_US du2(1.0,1);D_US du3(1.0,1,nullptr);//// E_US eu;                //错误没有默认构造E_US eu1(10);           //OK,调用A_US的,ival、dval被默认初始化(不进行初始化)E_US eu2(1.0,1);        //OK,调用A_US的,ival、dval被默认初始化(不进行初始化)E_US eu3(1.0,1,nullptr);//OK,调用A_US的,ival、dval被默认初始化(不进行初始化)//// F_US fu1(10);           //error,USTest无默认初始化导致错误// F_US fu2(1.0,1);        //error,USTest无默认初始化导致错误// F_US fu3(1.0,1,nullptr);//error,USTest无默认初始化导致错误//B12 b12(10);    //采用B12构造Z_US zus(0); // OK:Y_US 的初始化不调用 X_US 的默认构造函数//// DU1 d1(0); // error,非良构:从不同的 BU 基类子对象继承的构造函数/**OK:只有一个 BU 子对象。*这初始化虚 BU 基类,它初始化 AU 基类*然后如同用预置的默认构造函数*初始化 VU1 与 VU2 基类*/DU2 d2(0); // //B3 b3;b3.ival = 10;//b3.f(10);    //C3 c3;c3.f(10);   //可外部调用std::cout <<"-----1-----\n";//AT<int> at();           //warning: empty parentheses were disambiguated as a function declaration [-Wvexing-parse]BT<int,float> bt();     //warning: empty parentheses were disambiguated as a function declaration [-Wvexing-parse]CT<int> ct();           //warning: empty parentheses were disambiguated as a function declaration [-Wvexing-parse]//AT<USTest> at1();       //warning: empty parentheses were disambiguated as a function declaration [-Wvexing-parse]BT<USTest,float> bt1(); //warning: empty parentheses were disambiguated as a function declaration [-Wvexing-parse]CT<USTest> ct1();       //warning: empty parentheses were disambiguated as a function declaration [-Wvexing-parse]//AT<USTest> at2(1);      //OK// BT<USTest,USTest> bt2(1);  //error,多个构造冲突// BT<USTest,float> bt2(1);//error,base type 'float' fails to be a struct or class type float(int)// CT<USTest> ct2(1);  //error,多个构造冲突//DOP_US1 dop1,dop2;dop2 = dop1;    //OP_US operator=&DOP_US2 dop3,dop4;dop4 = dop3;    //OP_US2 operator=&DOP_US3 dop5,dop6;// dop6 = dop5;    //error: use of deleted function 'DOP_US3& DOP_US3::operator=(const DOP_US3&)'dop6 = std::move(dop5);//OP_US3 operator=&&
}

c/c++开发,无可避免的自定义类类型(篇五).using与类设计相关推荐

  1. 使用VS2010开发一个简单的自定义字段类型

    在SharePoint中创建自定义字段类型,必须完成两个工作:创建继承于SPField的字段类:编写字段的配置文件,声明字段的基本属性.字段的实现类和字段的呈现逻辑等. 首先在SharePoint站点 ...

  2. EA出品的java射击类游戏,盘点五款射击类RPG游戏:你喜欢这类型游戏吗?

    盘点五款射击类RPG游戏:你喜欢这类型游戏吗? 2020-06-04 18:04:06 3点赞 10收藏 3评论 RPG这种类型的游戏有很多,也是有许多玩家的喜欢.说到射击类型与RPG相结合的游戏,不 ...

  3. STL之容器适配器queue类-急流勇进篇(五)

    #include <iostream> #include <queue> #include <string>using namespace std;int main ...

  4. c/c++开发,无可避免的自定义类类型(篇三).类与虚函数

    深入而全面了解virtual虚函数与类设计关系 目录 一.virtual 函数说明符的作用 二.virtual 成员函数与普通成员函数 三.不必每个派生类重定义virtual 函数 四.派生类可以兼顾 ...

  5. NHibernate自定义集合类型(上):基本实现方式

    前天一篇文章中我说NHibernate的集合类型实现有些"尴尬",它无法使用自定义集合类型,设计也有些古怪--不过在许多朋友的指点下,我意识到NHibernate是可以使用自定义集 ...

  6. 如何设计好词袋模型BoW模型的类类型

    回顾过去自己写过的一些词袋模型,比如BoW图像检索Python实战.图像检索(CBIR)三剑客之BoF.VLAD.FV以及Bag of Words cpp实现,这些写出来的要么只是助于自己理解词袋模型 ...

  7. C++ 学习笔记之(19) new、delete表达式、RTTI(运行时类型识别)、枚举、类成员指针、嵌套类、局部类、位域、volatile、extern C

    C++ 学习笔记之(19) new.delete表达式.RTTI(运行时类型识别).枚举.类成员指针.嵌套类.局部类.位域.volatile.extern C C++ 学习笔记之(19) new.de ...

  8. JavaSE基础知识(五)--面向对象代码实现初步(实现一个简单的类类型代码)

    Java SE 是什么,包括哪些内容(五)? 本文内容参考自Java8标准 一.面向对象(代码实现): 首先,在这里我需要说明一个根本性的问题:实际上,面向对象编程包括了两部分,一个是你的编程思想,一 ...

  9. C++ 笔记(16)— 类和对象(类定义、类实例对象定义、访问类成员、类成员函数、类 public/private/protected 成员、类对象引用和指针)

    1. 类的定义 类定义是以关键字 class 开头,后跟类的名称.并在它后面依次包含类名,一组放在 {} 内的成员属性和成员函数,以及结尾的分号. 类声明将类本身及其属性告诉编译器.类声明本身并不能改 ...

  10. Scala类型系统——高级类类型(higher-kinded types)

    高级类类型就是使用其他类型构造成为一个新的类型,因此也称为 类型构造器(type constructors).它的语法和高阶函数(higher-order functions)相似,高阶函数就是将其它 ...

最新文章

  1. 【列表】python编程列表解析
  2. python ppt pdf linux,带你用Python玩转PPT
  3. Express调用mssql驱动公共类dbHelper
  4. 树莓派1 安装使用 ZeroTier
  5. 计算机管理器win,进入windows启动管理器,win启动管理器
  6. 使用JPA标准@ViewScoped通过分页,过滤和排序进行Primefaces DataTable延迟加载
  7. 【算法】蓝桥杯dfs深度优先搜索之排列组合总结
  8. linux环境下redis5.0的安装配置
  9. Oracle宣布在云上正式上线 自治事务处理数据库
  10. 集成测试:固定装置多于自动装置
  11. JVM学习(1)——通过实例总结Java虚拟机的运行机制(转)
  12. crontab下执行设置壁纸出错问题
  13. 简单的Verilog测试模板结构
  14. PyTorch源码解读之torch.utils.data.DataLoader
  15. 多个相同name的文本输入框,输入其中一个后,使剩下的不能输入值
  16. DXperience重编译汉化的方法
  17. 北航机试 16逆序数
  18. 用HTML5编写日历,js编写当天简单日历效果【实现代码】_javascript技巧
  19. 【畅捷通T+Cloud】12.3版本上线啦!
  20. Godot实用代码1000例

热门文章

  1. Android Auto 与Android Automotive
  2. 实战element 的rate使用iconfont图标
  3. C语言学习笔记一(C语言相关知识)
  4. lua中的bind函数,闭包函数,终于知道有啥用处了
  5. 初级产品经理读书心得 第二部分
  6. html js发送http请求数据格式,JS获取url参数,JS发送json格式的POST请求方法
  7. Java如何解析markdown_Java类库解析markdown文本
  8. vs窗口设计_1 实验室考勤助手
  9. Python3入门与进阶_课堂笔记
  10. memset函数(初始化)