C++基础知识学习总结2

阅读: 评论:0

C++基础知识学习总结2

C++基础知识学习总结2

上一篇

类的基础语法篇

类入门
#include <iostream>
#include <string>
using namespace std;
class Dog;//声明
class Cat
{friend istream &read(istream &, Cat &item);//class定义类时,访问修饰符之前默认是private
public:Cat() = default;Cat(const int &a) : Age(a) {}Cat(const int &a, const string &s) : Age(a), Name(s) {}Cat(istream &is);int age() const //const 常函数{//隐式内联,声明、定义都在类里面access_num++;return this->Age;}int sex() const{access_num++;return this->Sex;}string name() const{return this->Name;}Cat& setName(string name);Cat& setAge(const int age);void inlineTest();inline void inlineTest2();
private:int Sex = 1; int Age;string Name;mutable size_t access_num;//mutable修饰,在const函数里面也可以被修改
};
Cat::Cat(istream &is)
{read(is, *this);
}
inline void Cat::inlineTest()
{cout << "内联方式2:类中声明不加inline,类外定义加inline" << endl;
}
void Cat::inlineTest2()
{cout << "内联方式3:只在类中声明加inline" << endl;
}
Cat& Cat::setName(string name)
{Name = name;return *this;
}
Cat& Cat::setAge(int age)
{Age = age;return *this;
}
//类外部的函数想可访问类内的私有属性,以定义友元
istream &read(istream &is, Cat &item)
{//友元函数  可以访问私有属性 Sexis >> item.Age >> item.Name >> item.Sex;return is;
}
ostream &print(ostream &os, const Cat &item)
{os << "名称:" << item.name() << "t年龄:" << item.age();return os;
}
int main()
{Cat c;print(cout, c.setName("千任雪").setAge(18));c.inlineTest();cout << c.sex() << endl;return 0;
}
作用域
int big;
class Scope
{public:typedef string::size_type index;index test(index a, int big) const;private:int Age;int big;
};
Scope::index Scope::test(index a, int big) const {//int t = big;//是入参 big//int t = this->big; //类变量bigint t = ::big;//全局 bigreturn this->Age;
}
构造函数
class Sales_item
{public:Sales_item(const string &book) : book(book), num(4) {}Sales_item(const string &book, const double &price) : num(4) {this->price = price;this->book = book;}Sales_item(const double &sp, const double &price = 1.0) : price(price),small_price(sp),num(4) {//book是string类型,有默认构造函数,会自动初始化。}private:string book;double price;double small_price;const int num; //只能在初始化列表上初始化此值:1、const修饰的成员变量 2、引用类型的成员变量 3、没有默认构造函数的类类型//有上面三种情况,必须列表初始化,所以是不能使用Sales_item() = default;
};
....................................................
class Sales_item
{public:Sales_item() = default;Sales_item(const string &book) : book(book), price(1.1) {}Sales_item(const string &book, const double &price) : book(book), price(price) {}bool same_price(const Sales_item &item) const{return this->price == item.price;}private:string book;double price;double small_price;
};
Sales_item s;
Sales_item s2("ad", 1.1);
cout << s.same_price(s2) << endl;
Sales_item s3("jk");
.................................................
class CxString  
{public:explicit CxString(const int & i) :size(i) {}private:int size;
};
//如果类存在只有一个参数的构造函数(或者多个参数,但只有第一个参数没有默认值)时
CxString c = 8;//此时出现隐式转换,相当于 CxString c(8);
构造函数前加 explicit,它的作用是表明该构造函数是显示的, 而非隐式的。
和它对应的是implicit:(隐式的),但c++没有此关键词。
友元

声明为友元,不是类的成员,也能直接访问类的属性。

class A
{friend void test(Cat &c);//普通函数友元friend class friendClass;//类友元friend void friendMethod::testMethod();//类中方法友元private:int age;
};
static成员

所有的对象共用的成员。

class account
{public:account(string name, double amount) :name(name), amount(amount) {}double getAmount() const{return this->amount;}void add(double money){this->amount += money;}static void setRate(double newRate){Rate = newRate;}static double rate(){return Rate;}private:string name;double amount;static double Rate;//不可以在这初始化static const int test = 55;//特例:static const int 可以在这里初始化
};
double account::Rate = 0.2;
int main(int argc, char **argv)
{//account::Rate = 1;//public 才能在这里初始化account::setRate(1.2);account a("千任雪", 100);cout << a.getAmount() << endl;return 0;
}
复制(拷贝)构造函数&赋值操作符

复制(拷贝)构造函数&赋值操作符默认就有,一般不用自己写,如果类带有指针变量,并有动态内存分配,则必须重新写他们。
拷贝构造函数通常用于:
通过使用另一个同类型的对象来初始化新创建的对象。
复制对象把它作为参数传递给函数。
复制对象,并从函数返回这个对象。

class Sales_item
{public:Sales_item() : sold(0), price(0.0) {cout << "调用默认构造函数" << endl;}Sales_item(const string &isbin) : isbin(isbin), sold(0), price(0.0) {}//复制构造函数Sales_item(const Sales_item& item):isbin(item.isbin),sold(item.sold), price(item.price){cout << "调用复制构造函数" << endl;}//赋值操作符Sales_item& operator=(const Sales_item& item){cout << "调用赋值操作符" << endl;isbin = item.isbin;sold = item.sold;price = item.price;return *this;}void print(){cout << "isbin:" << isbin << "tsold:" << sold;}private:string isbin;unsigned sold;double price;
};Sales_item copy(Sales_item item)
{Sales_item temp;temp = item;return temp;
}
int main(int argc, char **argv)
{Sales_item s("测试");Sales_item ss(s);//复制构造函数Sales_item sss;sss = ss;//赋值操作符Sales_item i = string("66");//隐式的 调用了构造函数cout << "测试 copy" << endl;Sales_item res;res = copy(i);cout << "测试 vector" << endl;vector<Sales_item> v(5);cout << "测试 数组" << endl;Sales_item ids[] = {string("666")};return 0;
}
析构函数&深浅复制
class Sales_item
{public:Sales_item() :isbin(new string), sold(0), price(0.0) {cout << "调用默认构造函数" << endl;}Sales_item(string *&isbin) :isbin(isbin), sold(0), price(0.0) {}//复制构造函数Sales_item(const Sales_item &item):isbin(new string(*(item.isbin))), sold(item.sold), price(item.price){cout << "调用复制构造函数" << endl;}//赋值操作符Sales_item& operator=(const Sales_item& item){cout << "调用赋值操作符" << endl;isbin = new string;*isbin = *(item.isbin);sold = item.sold;price = item.price;return *this;}~Sales_item();private:string *isbin;unsigned sold;double price;
};
Sales_item::~Sales_item()
{cout << "析构函数.." << endl;delete isbin;//释放
}
int main(int argc, char **argv)
{string *i = new string("09j");//Sales_item x(i);Sales_item *xx = new Sales_item(i);Sales_item d ;d = *xx;delete xx;return 0;
}
-------------------c风格字符串---------------------------
#include <string.h> 添加这个头文件,提供strncpy。
class Sales_item
{public:Sales_item(int num, const char *cstr){this->num = num;this->cstr = new char[sizeof(cstr)];strncpy(this->cstr, cstr, sizeof(cstr) - 1);}//复制构造函数Sales_item(const Sales_item &item){cout << "调用复制构造函数" << endl;this->num = num;this->cstr = new char[sizeof(item.cstr)];strncpy(this->cstr, item.cstr, sizeof(item.cstr) - 1);}//赋值操作符Sales_item& operator=(const Sales_item& item){cout << "调用赋值操作符" << endl;this->num = num;this->cstr = new char[sizeof(item.cstr)];strncpy(this->cstr, item.cstr, sizeof(item.cstr) - 1);return *this;}~Sales_item();private:char *cstr;int num;
};
Sales_item::~Sales_item()
{cout << "析构函数.." << endl;delete cstr;//释放
}
int main(int argc, char **argv)
{Sales_item A(10, "44");return 0;
}
智能指针

浅复制容易出现野指针(悬垂指针),深复制(每一个对象中的指针都深复制,占用大量内存)。

class U_ptr //智能指针类
{friend class BhasPtr;private:int *ip;size_t used;U_ptr(int *p) : ip(p), used(1) {}~U_ptr() {cout << "U_ptr析构" << endl;delete ip;}
};
class BhasPtr
{public:BhasPtr():ptr(new U_ptr(0)), num(0) {}BhasPtr(int *p, int num):ptr(new U_ptr(p)), num(num) {}//复制构造BhasPtr(const BhasPtr &s):ptr(s.ptr), num(s.num) {++this->ptr->used;}BhasPtr& operator =(const BhasPtr &s){++s.ptr->used;if (--this->ptr->used == 0) delete ptr;this->ptr = s.ptr;//浅复制this->num = s.num;return *this;}~BhasPtr();private:U_ptr *ptr;int num;
};
BhasPtr::~BhasPtr()
{cout << "BhasPtr析构函数.." << endl;if (--this->ptr->used == 0) delete ptr;
}
int main(int argc, char **argv)
{int i = 1;BhasPtr p(&i, 0);//BhasPtr p2(p);BhasPtr p2;p2 = p;return 0;
}
重载操作符

菜鸟教程重载操作符

一般而言
定义为成员函数的运算符:赋值(=)、下标([ ])、 函数调用(( ))和成员访问箭头(->)。
重载的运算符会改变对象状态(如:复合赋值运算符(+=、 -=、 = 、 /= 、 %= 等), 递增、递减运算符,正(+)、负(-)运算符)或与类对象密切相关(如:解引用 *)。
定义非成员函数:+、 - 、x、 / 、 %,==、!=,>、 >= 、 <、 <=,位运算符。
输入(>>)、输出运算符(<<)必须是非成员函数。
输入、输出、等于、大于、小于建议定义友元函数,其他非成员函数可以通过友元函数转化。
把运算符定义为成员函数时,该运算符的左侧运算对象必须是运算符所属类的一个对象。

string s; //赋值运算符=是string的成员函数。
s = "world";//正确 
"world" = s;//错误 
class Sales_item
{friend ostream& operator<<(ostream &, const Sales_item &);friend istream& operator>>(istream &, Sales_item &);friend bool operator==(const Sales_item &,const Sales_item &);public:Sales_item(string &book, unsigned count, double price):isbn(book), units_sold(count), revenue(price * count) {}Sales_item() :units_sold(0), revenue(0.0) {}Sales_item& operator+=(const Sales_item &);//+= 定义成员函数private:string isbn;unsigned units_sold;double revenue;
};
Sales_item operator+(const Sales_item &,const Sales_item &);
ostream& operator<<(ostream& out, const Sales_item& item)
{out << item.isbn << "t" << venue << "t" << item.units_sold << endl;return out;
}
istream& operator>>(istream& in, Sales_item& item)//注意这里没有const
{double price;in >> item.isbn >> item.units_sold >> venue = item.units_sold * price;return in;
}
Sales_item& Sales_item::operator+=(const Sales_item &item)
{this->units_sold += item.units_sold;this->revenue += venue;return *this;
}
/**+ 不需要定义为成员函数,不能返回引用,因为 + 返回的是新的对象!!!int a = 0,b = 1,c; c = a+b;int i = 0; i += 1;
*/
Sales_item operator+(const Sales_item &l,const Sales_item &r)
{Sales_item l2(l);l2 += r;return l2;
}
inline bool operator==(const Sales_item &l,const Sales_item &r)
{return l.isbn == r.isbn &&venue == r.revenue &&l.units_sold == r.units_sold;
}
int main(int argc, char **argv)
{Sales_item a1;cin >> a1;Sales_item a2;cin >> a2;cout << a1 + a2 << endl;cout << "是否相同:" << (a1 == a2) << endl;system("pause");return 0;
}

重载赋值和下标操作符

class String
{
public:String(const char *chars){chars = chars ? chars : ""; //判断指针是不是空(是0就是空,尽量不要用NULL、nullptr)this->ptrChar = new char(strlen(chars) + 1);strncpy(this->ptrChar, chars, sizeof(chars) - 1);}String &operator=(const String &);String &operator=(const char *); //赋值 字符串字面值String &operator=(char);         //赋值 字符char &operator[](std::size_t index);//引用下标char operator[](std::size_t index) const;//const下标void print(){cout << this->ptrChar << endl;}~String(){cout << "析构...." << endl;delete[] this->ptrChar;}
private:char *ptrChar;
};
String &String::operator=(const String &s)
{if (strlen(this->ptrChar) != strlen(s.ptrChar)){char *temp = new char[strlen(s.ptrChar) + 1];delete[] this->ptrChar;this->ptrChar = temp;}strncpy(this->ptrChar, s.ptrChar, sizeof(s.ptrChar) - 1);return *this;
}
char &String::operator[](std::size_t index)
{if (index >= strlen(this->ptrChar)){throw out_of_range("out of ");}return this->ptrChar[index];
}
char String::operator[](std::size_t index) const
{cout << "调用const" << endl;if (index >= strlen(this->ptrChar)){throw out_of_range("out of ");}return this->ptrChar[index];
}
int main(int argc, char **argv)
{String s("rrr");String s2("6");s2 = s;s2.print();s.print();cout << s[1] << endl;const String s3("dsgrt");cout << s3[1] << endl;//调用 const下标return 0;
}

重载成员访问操作符

class String
{
public:String(const char *chars){chars = chars ? chars : ""; //判断指针是不是空this->ptrChar = new char(strlen(chars) + 1);strncpy(this->ptrChar, chars, sizeof(chars) - 1);}String(const String &s){this->ptrChar = new char(strlen(s.ptrChar) + 1);strncpy(this->ptrChar, s.ptrChar, sizeof(s.ptrChar) - 1);}void display() const{ cout << this->ptrChar << endl;}~String(){cout << "String析构...." << endl;delete[] this->ptrChar;}
private:char *ptrChar;
};
class Pointer
{public:Pointer(): ptr(0),used(new size_t(1)) {}Pointer(const String &n): used(new size_t(1)){this->ptr = new String(n);}~Pointer() {cout << "智能指针析构.." << endl;if (--(*this->used) == 0){delete this->ptr;delete this->used;} }Pointer(const Pointer& p){if (this != &p) {this->ptr = p.ptr;this->used = p.used;++(this->used);}}Pointer& operator=(const Pointer &p){cout << "赋值操作符重载" << endl;++(*p.used);if (--(*this->used) == 0){delete this->ptr;delete this->used;}this->ptr = p.ptr;//浅复制this->used = p.used;return *this;}String& operator*(){if (!this->ptr)throw runtime_error("ptr is null.");return *ptr;}String* operator->() const{if (!this->ptr)throw runtime_error("ptr is null.");return ptr;}private:String *ptr;size_t *used;  
};
int main(int argc, char **argv)
{// String s("rrr");// s.display();// String *sP = &s;// sP->display();Pointer p("c++");//p->display();//(*p).display();Pointer p2;p2 = p;p2->display();return 0;
}

重载自增自减操作符

class String
{
public:String(const char *chars){chars = chars ? chars : ""; //判断指针是不是空this->ptrChar = new char(strlen(chars) + 1);strncpy(this->ptrChar, chars, sizeof(chars) - 1);}String(const String &s){this->ptrChar = new char(strlen(s.ptrChar) + 1);strncpy(this->ptrChar, s.ptrChar, sizeof(s.ptrChar) - 1);}void display() const{ cout << this->ptrChar << endl;}~String(){cout << "String析构...." << endl;delete[] this->ptrChar;}String &operator++(){cout << "前加加" << endl;for(size_t i = 0; i < strlen(ptrChar); ++i){++ptrChar[i];}return *this;} String operator++(int){cout << "后加加" << endl;String temp(*this);++(*this);//函数的返回值不能为函数内部定义变量的引用//函数在调用完毕后,函数内部定义的变量空间被释放,无法访问,从而造成的错误。return temp;}String &operator--();String &operator--(int); 
private:char *ptrChar;
};
int main(int argc, char **argv)
{String s("ABC");String sold = s++;sold.display();s.display();return 0;
}
函数对象
//新增头文件
#include <list>
#include <algorithm>
//普通模板函数
template <typename T>
void FunDisPlayElement(const T &ele)
{cout << ele << endl;
}
//函数对象,功能更多
template <typename T>
struct DisPlayElement
{int count;DisPlayElement():count(0) {}void operator()(const T &ele) {++this->count;cout << ele << endl;}
};
int main(int argc, char **argv)
{vector<int> a;for (int i = 1; i <= 3; i++){a.push_back(i);}list<char> b;for (char c = 'a'; c <= 'e'; c++){b.push_back(c);}//stl算法for_each(a.begin(), a.end(), DisPlayElement<int>());DisPlayElement<char> mResult; mResult = for_each(b.begin(), b.end(), mResult);cout << "调用的次数:" << unt << endl;return 0;
}

一元函数对象:函数参数1个。
二元函数对象:函数参数2个。
一元谓词 函数参数1个,函数返回值是bool类型,可以作为一个判断式,谓词可以是一个仿函数,也可以是一个回调函数。
二元谓词 函数参数2个,函数返回值是bool类型。
之所以给返回布尔类型的函数对象专门命名,是因为谓词是用来为算法判断服务的。

----------------一元谓词----------------------------
template <typename T>
struct ISMultiple
{T  m_Divisor;ISMultiple(const T& divisor){m_Divisor = divisor ;} bool operator()(const T &ele) const{return ((ele % m_Divisor) == 0);} 
};
int main(int argc, char **argv)
{vector<int> a;for (int i = 1; i <= 20; i++){a.push_back(i);}ISMultiple<int> b(2);vector<int>::iterator iEle = find_if(a.begin(), a.end(), b);if (iEle != a.end()) {cout << "第一个2的倍数:" << *iEle << endl;} return 0;
}
-------------------------二元函数对象-----------------------------------
//二元函数
template <typename T>
struct Multiply 
{T operator()(const T &ele1, const T &ele2) const{return ele1 * ele2;} 
}; 
int main(int argc, char **argv)
{vector<int> a, b;for (int i = 1; i <= 20; i++){if (i % 2 == 0)a.push_back(i);elseb.push_back(i);  }vector<int> size(10);//每一位 对应相乘transform(a.begin(), a.end(), b.begin(), result.begin(), Multiply<int>());for(size_t i = 0;i < result.size(); i++){cout << result[i] << endl; }return 0;
}
--------------------------------二元谓词--------------------------------------
//二元谓词
//ctype.h 提供 tolower().
class CCompareStringNoCase
{public: bool operator() (const string &str1, const string &str2) const{string size(str1.size());transform(str1.begin(), d(), str1LowerCase.begin(), ::tolower);string size(str2.size()); transform(str2.begin(), d(), str2LowerCase.begin(), ::tolower);return (str1LowerCase < str2LowerCase);//小到大 排序} 
};
int main(int argc, char **argv)
{set<string, CCompareStringNoCase> names;names.insert("qian");names.insert("ren");names.insert("xue");names.insert("haHa");set<string, CCompareStringNoCase>::iterator nameFound = names.find("hAha"); if (nameFound != d()){cout << "wa  :"<< *nameFound << endl;}return 0;
}
转换操作符

转换函数: operator type() const ;
1、必须是成员函数,不能指定返回类型,必须没有形参,必须return一个指定类型的值。
2、不应该改变被转换的对象,通常定义为const。

class Cat
{public:Cat(string name, int age, double weight):name(name),age(age),weight(weight) {} operator int() const //转换函数{return age;}operator double() const{return weight;}private:int age;double weight;string name;
};
int main(int argc, char **argv)
{Cat c("甜甜圈", 1,2.2);int a = c;cout << a << endl;double d = c;cout << d << endl;return 0;
}
派生类
访问publicprotectedprivate
同一个类yesyesyes
派生类yesyesno
外部的类yesnono
一个派生类继承了所有的基类方法,但下列情况除外:
基类的构造函数、析构函数和拷贝构造函数。
基类的重载运算符。
基类的友元函数。
当一个类派生自基类,该基类可以被继承为 public、protected 或 private 几种类型,我们几乎不使用 protected 或 private 继承,通常使用 public 继承。
公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有保护成员来访问。
保护继承(protected): 当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。
私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。
接口继承:派生类只继承函数的接口,也就是声明;
实现继承:就是派生类同时继承函数的接口和实现。
class Animal
{public:int age;
};
class Cat : private Animal
{public:using Animal::age;//修改个别成员访问修饰符Cat() = default;
};
int main(int argc, char **argv)
{Cat c; c.age;//age 公有return 0;
}
-----------------------默认-----------------------------
class A : B//默认private
{int a;//默认private
}
struct A : B//默认public
{int a;//默认public
}

多态
1、从派生类到基类的转换。
2、引用或指针可以指向基类对象和派生类对象。
3、通过引用或指针调用虚函数发生动态绑定。

class Animal
{public:Animal(const string &name, const double weight): name(name),weight(weight) {}virtual void crt() const{cout << "name:" << name << "t体重:" << weight << endl;}string getName() const{return this->name;}private:string name;protected:double weight;
};
class Cat : public Animal
{public:Cat(string name, int age, double weight):Animal(name,age),age(age) {} void crt() const{cout << "调用Cat--name:" << this->getName() << "t体重:" << weight << endl;}private:int age;
};
int main(int argc, char **argv)
{Animal* c = new Cat("透透气", 12, 22.2); c->crt();delete c;return 0;
}

派生类中构造和析构
1:基类的构造->成员对象的构造->派生类的构造。
2:析构的顺序和构造相反!!!
对象转换
派生->基类:指针 转换/引用 转换–>动态绑定(多态)。
对象转换不会产生多态!!!
基类->派生类:需要强制转换。
A a;
B * b = static_cast<B *>(&a);
只能强制转换指针和引用。

继承和成员访问
class Animal
{public:static const size_t a = 6;int age;
};
class Cat : public Animal
{public:Cat() = default;void f(const Cat &b1,Cat *b2){cout << Animal::a << endl;cout << Cat::a << endl;cout << b1.a << endl;cout << b2->a << endl;cout << a << endl;}
};
int main(int argc, char **argv)
{Cat c = c;c.f(c,&c);return 0;
}
纯虚函数和抽象类

1、含有纯虚函数的类是抽象类。
2、抽象类只能作为派生类的基类,不能定义对象,但可以定义指针。在派生类实现该纯虚函数后,定义抽象类对象的指针,并指向或引用子类对象。
3、接口:只包含纯虚函数的抽象基类。
4、派生自抽象类的类必须实现纯虚函数或者它们必须也是抽象类。
虚函数和纯虚函数
1、虚函数和纯虚函数可以定义在同一个类(class)中,含有纯虚函数的类被称为抽象类(abstract class),而只含有虚函数的类(class)不能被称为抽象类(abstract class)。
2、虚函数可以被直接使用,也可以被子类(sub class)重载以后以多态的形式调用,而纯虚函数必须在子类(sub class)中实现该函数才可以使用,因为纯虚函数在基类(base class)只有声明而没有定义。
3、虚函数和纯虚函数都可以在子类(sub class)中被重载,以多态的形式被调用。
4、纯虚函数 virtual type funtion1()=0;
5、含有虚函数的类一般析构函数也要加virtual,因为如果不加基类指针删除派生类对象时,子类对象析构不会执行,产生内存泄漏。
6、 实现了纯虚函数的子类该纯虚函数在子类中就变成了虚函数,子类的子类(即孙子类)可以覆盖,孙子类的子类亦是如此(它一直都是虚函数)。
7、 虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数。
8、编译时多态性:通过重载函数实现。运行时多态性:通过虚函数实现。

class Animal
{public:Animal(){}virtual ~Animal(){ cout << "Animal析构..." << endl;}virtual int getAge() const = 0; //纯虚函数virtual void show() {} //虚函数virtual void f() = 0;  int age;
};
void Animal::f()
{cout << "纯虚函数一般不需要实现,可以实现。" << endl;
}
class Cat : public Animal
{public:Cat() = default;virtual ~Cat() {cout << &#" << endl;}int getAge() const{ return this->age;}void f() {Animal::f();}
};
int main(int argc, char **argv)
{Animal* c = new Cat();c->f();delete c;return 0;
}
多继承和虚基类
二义性问题
比如C类继承B、A,有同样的方法test()。
调用格式:
int main(int argc, char **argv)
{C c;c.B::a;C* cc = new C();cc->A::test();delete cc;return 0;
}
----------------------菱形继承会产生二义性-----------------------
lass D{......};
class B: public D{......};
class A: public D{......};
class C: public B, public A{.....};
这个继承会使D创建两个对象,浪费空间和二义性问题,要解决上面问题就要用虚拟继承格式。
虚继承--(在创建对象的时候会创建一个虚表)在创建父类对象的时候。
class D
{
public:D() { cout << "D()" << endl; }~D() { cout << "~D()" << endl; }
protected:int d;
};
class B : virtual public D
{
public:B() { cout << "B()" << endl; }~B() { cout << "~B()" << endl; }
protected:int b;
};class A : virtual public D
{
public:A() { cout << "A()" << endl; }~A() { cout << "~A()" << endl; }
protected:int a;
};class C: public B, public A
{
public:C() { cout << "C()" << endl; }~C() { cout << "~C()" << endl; }
protected:int c;
};
int main(int argc, char **argv)
{cout << sizeof(D) << endl;cout << sizeof(B) << endl;cout << sizeof(A) << endl;cout << sizeof(C) << endl;return 0;
}
虚继承,一般通过虚基类指针和虚基类表实现,每个虚继承的子类都有一个虚基类指针(64位中8字节)和虚基类表(不占用类对象的存储空间)。
虚基类表指针(virtual base table pointer)指向虚基类表(virtual table),虚表中记录了虚基类与本类的偏移地址。
对比虚函数:
都利用了虚指针(均占用类的存储空间)和虚表(均不占用类的存储空间)。
虚基类依旧存在继承类中,占用存储空间;虚函数不占用存储空间。
虚基类表存储的是虚基类相对直接继承类的偏移;而虚函数表存储的是虚函数地址。
命名空间

1、命名空间就是定义了一个范围,它可以嵌套,不同命名空间里变量或函数等的命名可以重名。
2、头文件里面尽量不要引入整个命名空间,用哪个引入哪个就行。

namespace namespace_name {// 代码声明
}
using namespace namespace_name;
using namespace namespace_name::name;//name可以是变量或函数...

下一篇-中篇

本文发布于:2024-02-03 03:00:21,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170690042148208.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:基础知识
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23