鱼C论坛

 找回密码
 立即注册
查看: 2151|回复: 17

[技术交流] C++

[复制链接]
发表于 2019-8-1 21:03:43 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 bin554385863 于 2019-8-3 17:42 编辑

2019年8月1日20:55:53
2019年8月3日17:43:55 修改类的定义


类的定义

  1. class mycomplex
  2. {
  3. private:
  4.     double re, im;//类的数据

  5. public:
  6.     mycomplex(double r = 0, double i = 0)
  7.         : re(r), im(i)
  8.     {
  9.         ;
  10.     }

  11.     double real() const//成员函数
  12.     {
  13.         return re;
  14.     }

  15.     double imag() const//成员函数
  16.     {
  17.         return im;
  18.     }
  19. };
复制代码



关键字:vector

快速动态数组,可以再运行阶段扩充数组

可以插入,删除,索引数组数据

定义:


vector<date type> datename;

vector<date type> datename(size, date)
向datename中写入size个date
360截图20190801211436699.jpg

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2019-8-8 00:53:22 | 显示全部楼层
本帖最后由 bin554385863 于 2019-8-14 00:12 编辑

2019年8月8日00:52:30
函数指针的用法
  1. #include <iostream>
  2. using namespace std;
  3. /*加法 */
  4. int add(int arg1, int arg2)
  5. {
  6.     return arg1 + arg2;
  7. }
  8. /*乘法 */
  9. double mult(double arg1, double arg2)
  10. {
  11.     return arg1 * arg2;
  12. }
  13. /*减法 */
  14. int subt(int arg1, int arg2)
  15. {
  16.     return arg1 - arg2;
  17. }
  18. /*除法 */
  19. double divi(double arg1, double arg2)
  20. {
  21.     return arg1 / arg2;
  22. }

  23. void calc(int arg1, int arg2)
  24. {
  25.     double res = 0;
  26.     int (*pcalc)(int, int);
  27.     double (*pcalc_c)(double, double);
  28.     char op;
  29.     cout << "请输入运算式" << endl;
  30.     cin >> arg1>>op>>arg2;
  31.     switch (op)
  32.     {
  33.     case '+':
  34.         pcalc = add;
  35.         res = pcalc(arg1, arg2);
  36.         break;
  37.     case '-':
  38.         pcalc = subt;
  39.         res = pcalc(arg1, arg2);
  40.         break;
  41.     case '*':
  42.         pcalc_c = mult;
  43.         res = pcalc_c(arg1, arg2);
  44.         break;
  45.     case '/':
  46.         pcalc_c = divi;
  47.         res = pcalc_c(arg1, arg2);
  48.         break;

  49.     default:
  50.         break;
  51.     }
  52.     cout << res << endl;
  53. }
  54. int main(int argc, char const *argv[])
  55. {
  56.     int b = 0, c = 0;
  57.     calc(b , c);
  58.     return 0;
  59. }
复制代码

-----------------------------------------------------------------------------------------------------------------------------------------------------
Windows PowerShell
版权所有 (C) Microsoft Corporation。保留所有权利。

PS E:\Users\86184\Documents\Code> & 'c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.24.1\debugAdapters\bin\WindowsDebugLauncher.exe' '--stdin=Microsoft-MIEngine-In-vxyzpdfk.c0n' '--stdout=Microsoft-MIEngine-Out-nlc2nijy.y3z' '--stderr=Microsoft-MIEngine-Error-exg2ivwk.zjt' '--pid=Microsoft-MIEngine-Pid-phhor1q0.0vm' '--dbgExe=E:\My Program\MinGW\bin\gdb.exe' '--interpreter=mi'
请输入运算式
3 +9
12
PS E:\Users\86184\Documents\Code> & 'c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.24.1\debugAdapters\bin\WindowsDebugLauncher.exe' '--stdin=Microsoft-MIEngine-In-3hgfugpp.4lk' '--stdout=Microsoft-MIEngine-Out-mdgp1rln.unc' '--stderr=Microsoft-MIEngine-Error-cwc0ujp0.sck' '--pid=Microsoft-MIEngine-Pid-vnhjpifc.de1' '--dbgExe=E:\My Program\MinGW\bin\gdb.exe' '--interpreter=mi'
请输入运算式
32*96
3072
PS E:\Users\86184\Documents\Code> & 'c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.24.1\debugAdapters\bin\WindowsDebugLauncher.exe' '--stdin=Microsoft-MIEngine-In-0aqcrvwu.njk' '--stdout=Microsoft-MIEngine-Out-xamzervn.uy0' '--stderr=Microsoft-MIEngine-Error-sx33tg4t.0su' '--pid=Microsoft-MIEngine-Pid-x10t3xb4.5ex' '--dbgExe=E:\My Program\MinGW\bin\gdb.exe' '--interpreter=mi'
请输入运算式
56-98
-42[/color
============================================================================================
  1. #include <iostream>
  2. using namespace std;
  3. /*加法 */
  4. double add(double arg1, double arg2)
  5. {
  6.     return arg1 + arg2;
  7. }
  8. /*乘法 */
  9. double mult(double arg1, double arg2)
  10. {
  11.     return arg1 * arg2;
  12. }
  13. /*减法 */
  14. double subt(double arg1, double arg2)
  15. {
  16.     return arg1 - arg2;
  17. }
  18. /*除法 */
  19. double divi(double arg1, double arg2)
  20. {
  21.     return arg1 / arg2;
  22. }

  23. void calc(double arg1, double arg2)
  24. {
  25.     while (1)
  26.     {
  27.         double res = 0;
  28.         double (*pcalc)(double, double);
  29.         char op;
  30.         cout << "请输入运算式" << endl;
  31.         cin >> arg1 >> op >> arg2;
  32.         switch (op)
  33.         {
  34.         case '+':
  35.             pcalc = add;
  36.             res = pcalc(arg1, arg2);
  37.             break;
  38.         case '-':
  39.             pcalc = subt;
  40.             res = pcalc(arg1, arg2);
  41.             break;
  42.         case '*':
  43.             pcalc = mult;
  44.             res = pcalc(arg1, arg2);
  45.             break;
  46.         case '/':
  47.             pcalc = divi;
  48.             res = pcalc(arg1, arg2);
  49.             break;

  50.         default:
  51.             break;
  52.         }
  53.         cout << arg1 << op << arg2 << '=' << res << endl;
  54.     }
  55. }
  56. int main(char argc, char const *argv[])
  57. {
  58.     int b = 0, c = 0;
  59.     calc(b, c);
  60.     return 0;
  61. }
复制代码

----------------------------------------------------------------------------------------------------------------------

PS E:\Users\86184\Documents\Code> & 'c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.24.1\debugAdapters\bin\WindowsDebugLauncher.exe' '--stdin=Microsoft-MIEngine-In-alch3axa.k5g' '--stdout=Microsoft-MIEngine-Out-20tna1oi.b2f' '--stderr=Microsoft-MIEngine-Error-gxxl5wak.ars' '--pid=Microsoft-MIEngine-Pid-bf3fmh1m.cx1' '--dbgExe=E:\My Program\MinGW\bin\gdb.exe' '--interpreter=mi'
请输入运算式
23+63
23+63=86
请输入运算式
63*98
63*98=6174
请输入运算式
63/54
63/54=1.16667
请输入运算式
87-96
87-96=-9
请输入运算式
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-11 11:25:26 | 显示全部楼层
本帖最后由 bin554385863 于 2019-8-11 12:02 编辑

2019年8月11日11:23:22
引用&指针
  1. #include <iostream>
  2. #include <cstdio>
  3. int main(int argc, char const *argv[])
  4. {
  5.     char str = 'p';
  6.     /*引用 */
  7.     char &Refstr = str;
  8.     std::cout << "初始值 " << '\n'
  9.               << "str "
  10.               << "= " << str << std::endl;
  11.     Refstr = 'f';
  12.     std::cout << "引用改值 " << '\n'
  13.               << "str "
  14.               << "= " << str << std::endl;
  15.     /*指针 */
  16.     char *pstr = &str;
  17.     *pstr = 'o';
  18.     std::cout << "指针改值 " << '\n'
  19.               << "str "
  20.               << "= " << str << std::endl;
  21.     std::cout << "指针本身的值" << '\n'
  22.               << "pstr "
  23.               << "= " << std::hex << (void *)pstr;
  24.     //printf("%#X", pstr);
  25.     return 0;
  26. }
复制代码

-----------------------------------------------------------------------------------------
Microsoft Windows [版本 10.0.16299.1087]
(c) 2017 Microsoft Corporation。保留所有权利。

E:\Users\86184\Documents\Code>c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.24.1\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-5edmn1ex.z4c --stdout=Microsoft-MIEngine-Out-dd5gwwiv.yrl --stderr=Microsoft-MIEngine-Error-auibg2v3.efm --pid=Microsoft-MIEngine-Pid-x2jmfct3.4uu "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi
初始值
str = p
引用改值
str = f
指针改值
str = o
指针本身的值
pstr = 0x61ff17

E:\Users\86184\Documents\Code>


引用不是对象因此不能对它取地址,他只是拥有指针功能的,变量的一个别名,就像人的外号,而指针则相当于身份证号
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-12 19:39:25 | 显示全部楼层
本帖最后由 bin554385863 于 2019-8-14 00:13 编辑

2019年8月12日19:35:37

C++11 auto和decltype关键字

  1. #include <iostream>
  2. #include <typeinfo>
  3. using namespace std;
  4. int main(int argc, char const *argv[])
  5. {
  6.     float const b = 100u;//b是常量不能改变它的值
  7.     auto a = b;//auto通过数据的初始值来判断变量的类型。auto忽略了b的const声明
  8.     a = 0;//变量a不是常量,可以改变它的值
  9.     decltype(b) c = 0;//decltype返回操作数的类型,并使用它定义别的变量.c是常量它的值无法改变。decltype不会忽略const关键字。
  10.     decltype(a) e;//e不是常量
  11.     cout<<typeid(c).name()<<endl;
  12.     /*它俩的区别是:auto会忽略左值的const声明。decltype()则不会*/
  13.     return 0;
  14. }
复制代码

--------------------------------------------------------------------------------------Microsoft Windows [版本 10.0.16299.1087]
(c) 2017 Microsoft Corporation。保留所有权利。

E:\Users\86184\Documents\Code>c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.24.1\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-wmpqbpum.apa --stdout=Microsoft-MIEngine-Out-iq32vdue.mej --stderr=Microsoft-MIEngine-Error-veqrbw3z.oya --pid=Microsoft-MIEngine-Pid-jufr4wdn.vvm "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi
f

E:\Users\86184\Documents\Code>

==================================================================
因为是mingGW所以输出的是类型缩写,用VS则会输出全称。

decltype((a)):双层括号返回的是引用类型,相当于
int &b = a;
decltype(b);

要想用auto定义一个常量必须加const关键字,
const auto c = 0;

==============================================

C++11范围for循环

  1. #include <iostream>
  2. /*范围for循环*/
  3. int main(int argc, char const *argv[])
  4. {
  5.     using std::cout;
  6.     using std::endl;
  7.     int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  8.     for (int num : arr) //for(存储数组元素的临时变量 :数组指针)
  9.     {
  10.         cout << num << ' ';
  11.     }
  12.     return 0;
  13. }

复制代码

-----------------------------------------------------------------------------
Microsoft Windows [版本 10.0.16299.1087]
(c) 2017 Microsoft Corporation。保留所有权利。

E:\Users\86184\Documents\Code>c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.24.1\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-lacyeeus.y5c --stdout=Microsoft-MIEngine-Out-fukloctk.1nv --stderr=Microsoft-MIEngine-Error-j2zzod5r.wrd --pid=Microsoft-MIEngine-Pid-g3nrssx2.sku "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi
0 1 2 3 4 5 6 7 8 9
E:\Users\86184\Documents\Code>

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-13 22:52:19 | 显示全部楼层
本帖最后由 bin554385863 于 2019-8-14 00:13 编辑

2019年8月13日22:43:21
  1. #include <iostream>
  2. #include <string>
  3. #include <cctype>
  4. int main(int argc, char const *argv[])
  5. {
  6.     using namespace std;
  7.     string str1 = "hello";
  8.     string str2 = "world";
  9.     string strc, strg;
  10.     /*getling可以读取空格,以回车结束*/
  11.     getline(cin, strg);
  12.     /*cin遇到空白字符就结束读取*/
  13.     cin >> strc;
  14.     cout<<endl;
  15.     cout << "str1 = " << str1 << endl;
  16.     cout << "str2 = " << str2 << endl;
  17.     cout << "strc = " << strc << endl;
  18.     cout << "strg = " << strg << endl;
  19.     /*string类型的字符串可以用加号拼接,用关系运算符进行比较*/
  20.     str1 = str1 + " " + str2 + " " + strg + " " + strc;
  21.     cout << "str1 = " << str1 << endl;
  22.     decltype(str1.size()) count = 0;
  23.     /*范围for循环*/
  24.     for (char c : str1)
  25.     {
  26.         /*ispunct()判断字符是不是符号*/
  27.         if (ispunct(c))
  28.         {
  29.             count++;
  30.         }
  31.         /*toupper()将小写字符转换成大写字符*/
  32.         cout << (char)toupper(c);
  33.     }
  34.     cout << "总共有" << count << "个符号";
  35.     return 0;
  36. }
复制代码

------------------------------------------------------------------------------------------------
Microsoft Windows [版本 10.0.16299.1087]
(c) 2017 Microsoft Corporation。保留所有权利。

E:\Users\86184\Documents\Code>c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.24.1\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-br3thiie.l4p --stdout=Microsoft-MIEngine-Out-k0qugrwq.5k1 --stderr=Microsoft-MIEngine-Error-cbjsa24n.1s2 --pid=Microsoft-MIEngine-Pid-zsskfzrp.cbo "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi
c language
c++!!!

str1 = hello
str2 = world
strc = c++!!!
strg = c language
str1 = hello world c language c++!!!
HELLO WORLD C LANGUAGE C++!!!
总共有5个符号

E:\Users\86184\Documents\Code>

=================================================================================
360截图20190813225604107.gif

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-14 19:08:39 | 显示全部楼层
本帖最后由 bin554385863 于 2019-8-15 12:16 编辑

2019年8月14日19:07:56
向量vector的初始化
  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4. int main(int argc, char const *argv[])
  5. {
  6.     using namespace std;
  7.     /*列表初始化*/
  8.     vector<string> str = {"hello world"};
  9.     /*构造初始化*/
  10.     vector<string> str1(10, "A");
  11.     /*读取输入初始化*/
  12.     vector<string> str2;
  13.     string cintxt;
  14.     while (getline(cin, cintxt))
  15.     {
  16.         str2.push_back(cintxt);
  17.         if (getchar() == '\n')
  18.         {
  19.             break;
  20.         }     
  21.     }
  22.     cout << "列表初始化: "
  23.          << "str = ";
  24.     for (auto strc : str)
  25.     {
  26.         cout << strc;
  27.     }
  28.     cout << endl;

  29.     cout << "构造初始化: "
  30.          << "str1 = ";
  31.     for (auto str1c : str1)
  32.     {
  33.         cout << str1c;
  34.     }
  35.     cout << endl;

  36.     cout << "读取输入初始化: "
  37.          << "str2 = ";
  38.     for (auto str2c : str2)
  39.     {
  40.         cout << str2c;
  41.     }
  42.     cout << endl;
  43.     return 0;
  44. }
复制代码

*****************************************************************************
Microsoft Windows [版本 10.0.16299.1087]
(c) 2017 Microsoft Corporation。保留所有权利。

E:\Users\86184\Documents\Code>c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.24.1\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-cz0l4q3a.zml --stdout=Microsoft-MIEngine-Out-vxgsh2vk.r4p --stderr=Microsoft-MIEngine-Error-nuzcpwcp.1nd --pid=Microsoft-MIEngine-Pid-2hpomys3.ecs "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi
****** ********* ********** **********

列表初始化: str = hello world
构造初始化: str1 = AAAAAAAAAA
读取输入初始化: str2 = ****** ********* ********** **********

E:\Users\86184\Documents\Code>

===========================================================================
练习
  1. #include <iostream>
  2. #include <cctype>
  3. #include <vector>
  4. #include <string>
  5. /*输入一组字符串,转换成大写字符后,按横输出*/
  6. int main(int argc, char const *argv[])
  7. {
  8.     using namespace std;
  9.     /*临时变量*/
  10.     string word;
  11.     /*向量str*/
  12.     vector<string> str;
  13.     cout << "请输入字符串" << endl;
  14.     /*临时变量接受输入*/
  15.     getline(cin, word);
  16.     /*将临时变量的数据加入向量str*/
  17.     str.push_back(word);
  18.     /*加入换行符并转换大小写*/
  19.     cout<<endl;
  20.     cout<<"输出结果"<<endl;
  21.     for (string c : str)
  22.     {
  23.         for (char b : c)
  24.         {
  25.             
  26.             if (b == ' ')
  27.             {
  28.                 b = '\n';
  29.             }
  30.             else
  31.             {
  32.                 b = (char)toupper(b);
  33.             }
  34.             cout<<b;
  35.         }
  36.     }
  37.     return 0;
  38. }
复制代码

***************************************************************************
Microsoft Windows [版本 10.0.16299.1087]
(c) 2017 Microsoft Corporation。保留所有权利。

E:\Users\86184\Documents\Code>c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.24.1\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-4s4jmhdg.mpa --stdout=Microsoft-MIEngine-Out-qizf4ybs.qzw --stderr=Microsoft-MIEngine-Error-yfusqgvx.q0o --pid=Microsoft-MIEngine-Pid-fshxcw4u.gg2 "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi
请输入字符串
hello c++ language you are crazy

输出结果
HELLO
C++
LANGUAGE
YOU
ARE
CRAZY

E:\Users\86184\Documents\Code>

=============================================================================================
练习
  1. #include <iostream>
  2. #include <vector>
  3. #include <cctype>
  4. /*定义一个vector对象,读取一组数字,计算相邻元素的和,和头尾相加的和*/
  5. int main(int argc, char const *argv[])
  6. {
  7.     using namespace std;
  8.     int a = 1;
  9.     vector<int> veca;
  10.     /*输入数据*/
  11.     cout << "请输入数据" << endl;
  12.     while (a)
  13.     {
  14.         cin >> a;
  15.         /*舍去结束符0*/
  16.         if (!a)
  17.         {
  18.             break;
  19.         }
  20.         veca.push_back(a);
  21.     }
  22.     /*查看向量的元素*/
  23.     cout << "对象元素" << endl;
  24.     for (auto a : veca)
  25.     {
  26.         cout << a << "  ";
  27.     }
  28.     cout << endl;
  29.     decltype(veca.size()) i = 0, s = veca.size();
  30.     /*计算相邻两个元素的和*/
  31.     cout << "相邻元素的和" << endl;
  32.     for (; i < s - 1; i++)
  33.     {
  34.         cout << veca[i] << " + " << veca[i + 1] << " = " << veca[i] + veca[i + 1] << "    ";
  35.     }
  36.     cout << endl;
  37.     /*计算头尾相加的和*/
  38.     cout << "头尾相加的和" << endl;
  39.     for (i = 0; i < (s + 1) / 2; i++)
  40.     {
  41.         cout << veca[i] << " + " << veca[s - 1 - i] << " = " << veca[i] + veca[s - 1 - i] << "   ";
  42.     }
  43.     return 0;
  44. }
复制代码

***********************************************************************************************
Microsoft Windows [版本 10.0.16299.1087]
(c) 2017 Microsoft Corporation。保留所有权利。

E:\Users\86184\Documents\Code>c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.24.1\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-t40m2dyf.5po --stdout=Microsoft-MIEngine-Out-kosvuagf.pqm --stderr=Microsoft-MIEngine-Error-ioyqbdlx.1lg --pid=Microsoft-MIEngine-Pid-hsh32dli.eyz "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi
请输入数据
1 2 3 4 5 6 7 8 9 0
对象元素
1  2  3  4  5  6  7  8  9
相邻元素的和
1 + 2 = 3    2 + 3 = 5    3 + 4 = 7    4 + 5 = 9    5 + 6 = 11    6 + 7 = 13    7 + 8 = 15    8 + 9 = 17
头尾相加的和
1 + 9 = 10   2 + 8 = 10   3 + 7 = 10   4 + 6 = 10   5 + 5 = 10

E:\Users\86184\Documents\Code>

---------------------------------------------------------------------------------------------------------------------------------------------------
修正
  1. #include <iostream>
  2. #include <vector>
  3. #include <cctype>
  4. /*定义一个vector对象,读取一组数字,计算相邻元素的和,和头尾相加的和*/
  5. int main(int argc, char const *argv[])
  6. {
  7.     using namespace std;
  8.     int a = 1;
  9.     bool flag = true;
  10.     vector<int> veca;
  11.     /*输入数据*/
  12.     cout << "请输入数据" << endl;
  13.     while (true)
  14.     {
  15.         cin >> a;
  16.         /*舍去结束符0*/
  17.         if (!a)
  18.         {
  19.             break;
  20.         }
  21.         veca.push_back(a);
  22.     }
  23.     decltype(veca.size()) i = 0, s = veca.size();
  24.     /*判断是否非空集合*/
  25.     if (veca.empty() || (s < 2))
  26.     {
  27.         cout << "请输入两个以上的非零数字";
  28.         return 0;
  29.     }
  30.     /*查看向量的元素*/
  31.     cout << "对象元素" << endl;
  32.     for (auto a : veca)
  33.     {
  34.         cout << a << "  ";
  35.     }
  36.     cout << endl;
  37.     /*计算相邻两个元素的和*/
  38.     cout << "相邻元素的和" << endl;
  39.     for (; i < s - 1; i++)
  40.     {
  41.         cout << veca[i] << " + " << veca[i + 1] << " = " << veca[i] + veca[i + 1] << "    ";
  42.     }
  43.     cout << endl;
  44.     /*计算头尾相加的和*/
  45.     cout << "头尾相加的和" << endl;
  46.     for (i = 0; i < (s + 1) / 2; i++)
  47.     {
  48.         cout << veca[i] << " + " << veca[s - 1 - i] << " = " << veca[i] + veca[s - 1 - i] << "   ";
  49.     }
  50.     return 0;
  51. }
复制代码

***********************************************************************************
(c) 2017 Microsoft Corporation。保留所有权利。

E:\Users\86184\Documents\Code>c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.24.1\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-l1pit2dt.gjr --stdout=Microsoft-MIEngine-Out-k13clai2.sus --stderr=Microsoft-MIEngine-Error-0bil35nt.k1b --pid=Microsoft-MIEngine-Pid-344d1as5.uzi "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi
请输入数据
a
请输入两个以上的非零数字

E:\Users\86184\Documents\Code>cmd /C "c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.24.1\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-pa1puxjz.vje --stdout=Microsoft-MIEngine-Out-hpyztzpx.p5p --stderr=Microsoft-MIEngine-Error-szvzjs0p.22y --pid=Microsoft-MIEngine-Pid-hh00x2dr.w1z "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi "
请输入数据
1 2 3 30 8545 878 a
对象元素
1  2  3  30  8545  878
相邻元素的和
1 + 2 = 3    2 + 3 = 5    3 + 30 = 33    30 + 8545 = 8575    8545 + 878 = 9423
头尾相加的和
1 + 878 = 879   2 + 8545 = 8547   3 + 30 = 33

E:\Users\86184\Documents\Code>

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-15 17:35:04 | 显示全部楼层
2019年8月15日17:35:00
迭代器
360截图20190815173356289.gif
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-17 12:34:08 | 显示全部楼层
本帖最后由 bin554385863 于 2019-8-17 21:23 编辑

2019年8月17日12:10:30
  1. #include <iostream>
  2. #include <vector>
  3. #include <cctype>
  4. #include <cmath>
  5. /*判断字符串是不是一个整数*/
  6. bool isnumber(std::string &strargs)
  7. {
  8.     bool flag = true;
  9.     for (char cargs : strargs)
  10.     {
  11.         if (!isdigit(cargs))
  12.         {
  13.             flag = false;
  14.             break;
  15.         }
  16.     }
  17.     return flag;
  18. }
  19. /*将数字字符串转换成整数*/
  20. std::vector<int> tonumber(std::string &strargs)
  21. {
  22.     std::vector<int> vecargs;
  23.     const int size = strargs.size();
  24.     double result = 0;
  25.     for (size_t i = 0; i < size; i++)
  26.     {
  27.         result += (strargs[i] - 48) * pow(10, size - 1 - i);
  28.     }
  29.     vecargs.push_back(result);
  30.     result = 0;
  31.     return vecargs;
  32. }
复制代码

*****************************************************************************
  1. #include <iostream>
  2. #include <vector>
  3. #include <cctype>
  4. #include <cmath>
  5. #include "E:\Users\86184\Documents\Code\Study\0_0_0_MyC++func.cpp"
  6. /*使用迭代器使输入的数字翻倍输出*/
  7. int main(int argc, char const * argv[])
  8. {
  9.         using namespace std;
  10.         double ynum = 0;
  11.         string wnum;
  12.         vector<int> intnum;

  13.         while (true)
  14.         {
  15.                 cout << "请输入数字" << endl;

  16.                 cin >> wnum;
  17.                 if (!isnumber(wnum))
  18.                 {
  19.                         cout << "输入含有其他字符,请重新输入" << endl;
  20.                         continue;
  21.                 }
  22.                 intnum = tonumber(wnum);
  23.                 vector<int>::iterator it = intnum.begin();
  24.                 for (; it != intnum.end(); ++it)
  25.                 {
  26.                         *it = *it * 2;
  27.                 }
  28.                 for (int num : intnum)
  29.                 {
  30.                         cout << wnum << " X 2 = " << num << "  ";
  31.                 }
  32.                 cout<<endl;
  33.         }

  34.         return 0;
  35. }
复制代码

===================================================================
E:\Users\86184\Documents\Code>c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.24.1\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-0mcjprfn.ln5 --stdout=Microsoft-MIEngine-Out-aiq00ynt.j4f --stderr=Microsoft-MIEngine-Error-gsbuvl41.e2z --pid=Microsoft-MIEngine-Pid-e3rxfvlh.qsi "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi
请输入数字
q
输入含有其他字符,请重新输入
请输入数字
+
输入含有其他字符,请重新输入
请输入数字
123 1000 3
123 X 2 = 246
请输入数字
1000 X 2 = 2000
请输入数字
3 X 2 = 6
请输入数字


E:\Users\86184\Documents\Code>

==================================================================
数组和向量
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. /*使用数组初始化集合*/
  5. int main(int argc, char const *argv[])
  6. {
  7.     using namespace std;
  8.     int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 02, 35, 3, 54};
  9.     /*使用数字初始化集合*/
  10.     vector<int> vec(begin(arr), end(arr));//使用begin()和end()函数,数组名作为参数,获取数组的头指针和尾部指针
  11.     vector<int> vecx(begin(arr) + 5, begin(arr) + 10);
  12.     for (int i : vec)
  13.     {
  14.         cout << i << "  ";
  15.     }
  16.     cout << endl;
  17.     for (int j : vecx)
  18.     {
  19.         cout << j << "  ";
  20.     }
  21.     return 0;
  22. }
复制代码

------------------------------------------------------------------------------------------------------
Microsoft Windows [版本 10.0.16299.1087]
(c) 2017 Microsoft Corporation。保留所有权利。

E:\Users\86184\Documents\Code>c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.24.1\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-kpilswng.fil --stdout=Microsoft-MIEngine-Out-lllfevgw.4pb --stderr=Microsoft-MIEngine-Error-f4342yjf.phl --pid=Microsoft-MIEngine-Pid-edkkjwrg.zlu "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi
0  1  2  3  4  5  6  7  8  9  1  2  35  3  54
5  6  7  8  9

E:\Users\86184\Documents\Code>

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-20 01:07:30 | 显示全部楼层
本帖最后由 bin554385863 于 2019-8-20 01:20 编辑

2019年8月20日01:08:15
  1. #include <iostream>
  2. #include <initializer_list>
  3. #include <vector>
  4. /*可变参数类型std::initializer_list<type>*/
  5. double sum(const std::initializer_list<int> &arg)
  6. {
  7.     double sum = 0;
  8.     for(int num: arg)
  9.     {
  10.         sum += num;
  11.     }
  12.     return sum;
  13. }
  14. int main(int argc, char const *argv[])
  15. {
  16.     const int a = 10;
  17.     const int b = 100, c = 63;
  18.     /*std::initializer_list<int>参数列表元素全都是常量*/
  19.     std::cout<<sum({1,-2,3,-4,5,-6,7,-8,9})<<std::endl;
  20.     std::cout<<sum({a, b, c});
  21.     return 0;
  22. }
复制代码

------------------------------------------------------------------------------------

E:\Users\86184\Documents\Code>cmd /C "c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.24.1\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-dpp1rvoj.vjf --stdout=Microsoft-MIEngine-Out-0knopx0m.s0l --stderr=Microsoft-MIEngine-Error-nrqlrhy2.j3p --pid=Microsoft-MIEngine-Pid-0nqtwlhr.btm "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi "
5
110

E:\Users\86184\Documents\Code>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-24 01:45:16 | 显示全部楼层
2019年8月24日01:44:22
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include<algorithm>
  5. using namespace std;
  6. /*编写一个函数来查找字符串数组中的最长公共前缀。

  7. 如果不存在公共前缀,返回空字符串 ""*/
  8. string longestCommonPrefix(vector<string> &strs)
  9. {
  10.         string result;
  11.         /*判定向量是否为空*/
  12.         if (strs.empty())
  13.         {
  14.                 result = {""};
  15.         }
  16.         else
  17.         {
  18.                 size_t s = strs.size();
  19.                 if (s == 1)
  20.                 {
  21.                         return strs[0];
  22.                 }
  23.                 else if (s > 1)
  24.                 {
  25.                         /*构造向量字符串元素跳过对{"c", "c",...}和{"","",....}类似的向量元素的判定*/
  26.                         strs[0] = strs[0] + "10lo";
  27.                         strs[1] = strs[1] + "l01o";
  28.                         /*初始化计数器*/
  29.                         size_t count = 0;
  30.                         /*定义数组,保存对比的计数结果*/
  31.                         vector<int> arr;
  32.                         for (size_t i = s - 1; i > 0; i--)
  33.                         {
  34.                                 for (size_t j = 0;; j++)
  35.                                 {
  36.                                         if (strs[0][j] != strs[i][j])
  37.                                         {
  38.                                                 break;
  39.                                         }
  40.                                         count++;
  41.                                 }
  42.                                 arr.push_back(count);
  43.                                 /*重新初始化计数器*/
  44.                                 count = 0;
  45.                         }
  46.                         size_t sa = arr.size();
  47.                         /*从小到大排序*/
  48.                         sort(arr.begin(), arr.end());               
  49.                         /*首位元素就是最终结果*/
  50.                         if (arr[0] == 0)
  51.                         {
  52.                                 result = {""};
  53.                         }
  54.                         else
  55.                         {
  56.                                 for (size_t i = 0; i < arr[0]; i++)
  57.                                 {
  58.                                         result.push_back(strs[1][i]);
  59.                                 }
  60.                         }
  61.                 }
  62.         }
  63.         return result;
  64. }
  65. int main(int argc, char const *argv[])
  66. {
  67.         vector<string> a = {"boot", "boom", "boor", "boall"};
  68.         vector<string> b = {"baac", "bacc", "b"};
  69.         vector<string> c = {"flower"};
  70.         vector<string> d = {"",""};
  71.         vector<string> e =
  72.                 {
  73.                         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  74.                         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  75.                         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  76.                         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  77.                         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  78.                         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  79.                         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  80.                         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  81.                         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  82.                         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  83.                         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  84.                 };
  85.         cout << longestCommonPrefix(a) << endl;
  86.         cout << longestCommonPrefix(b) << endl;
  87.         cout << longestCommonPrefix(c) << endl;
  88.         cout << longestCommonPrefix(d) << endl;
  89.         cout << longestCommonPrefix(e) << endl;
  90.         return 0;
  91. }
复制代码

-------------------------------------------------------------------------------------------------------------------
Microsoft Windows [版本 10.0.16299.1087]
(c) 2017 Microsoft Corporation。保留所有权利。

E:\Users\86184\Documents\Code>c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.25.0\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-2uug3wdg.re0 --stdout=Microsoft-MIEngine-Out-fgrkj5jj.np0 --stderr=Microsoft-MIEngine-Error-hm0qrys1.x3k --pid=Microsoft-MIEngine-Pid-nxksjd20.xqb "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi
bo
b
flower

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa


E:\Users\86184\Documents\Code>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-25 20:12:39 | 显示全部楼层
2019年8月25日20:05:53
委托构造函数定义
function():func(0, 0,....){}
无参数构造函数 func()委托有参数构造函数funct(args, ....),构造对象

复制构造函数
classname(args,...  );---默认构造函数
classname(const classname &objectname);------复制构造函数
classname(const classname &objectname) = delete;-----禁止复制构造


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-28 01:25:49 | 显示全部楼层
2019年8月28日01:23:54
一个完整的类的定义
  1. #include <iostream>
  2. class clock
  3. {
  4. private:
  5.     /*成员变量*/
  6.     int Hour, Minute, Second;

  7. public:
  8.     /*有参数的构造函数*/
  9.     clock(int hour, int minute, int second) : Hour(hour), Minute(minute), Second(second) {}
  10.     /*默认构造函数委托有参数的构造函数初始化*/
  11.     clock() : clock(0, 0, 0) {}
  12.     /*复制构造函数*/
  13.     clock(const clock &oarg);
  14.     /*声明析构函数.当对象销毁时系统会自动调用析构函数做最后的清理*/
  15.     ~clock();
  16.     /*声明成员函数*/
  17.     void setClock(int hour, int minute, int second);
  18.     void showClock();
  19. };
  20. /*定义复制构造函数*/
  21. clock::clock(const clock &oarg)
  22. {
  23.     Hour = oarg.Hour;
  24.     Minute = oarg.Minute;
  25.     Second = oarg.Second;
  26. }
  27. /*定义成员函数*/
  28. void clock::setClock(int hour, int minute, int second)
  29. {
  30.     Hour = hour;
  31.     Minute = minute;
  32.     Second = second;
  33. }
  34. void clock::showClock()
  35. {
  36.     std::cout << Hour << ":" << Minute << ":" << Second << std::endl;
  37. }
  38. /*定义析构函数*/
  39. clock::~clock()
  40. {
  41.     std::cout<<"调用析构函数"<<std::endl;
  42. }
  43. int main(int argc, char const *argv[])
  44. {
  45.     /*若没有定义有参数的构造函数,下面的语句就会报错*/
  46.     clock a = {2, 3, 6};
  47.     /*若自己没有定义无参数的构造函数,则编译器会自己添加一个默认的构造函数*/
  48.     clock b;
  49.     /*调用成员函数*/
  50.     a.showClock();
  51.     b.showClock();
  52.     b.setClock(24, 20, 59);
  53.     b.showClock();
  54.     clock c = b;
  55.     c.showClock();
  56.     return 0;
  57. }
复制代码

-----------------------------------------------------------------------------------------------------
Microsoft Windows [版本 10.0.16299.1087]
(c) 2017 Microsoft Corporation。保留所有权利。

E:\Users\86184\Documents\Code>c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.25.0\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-iywbbnha.vug --stdout=Microsoft-MIEngine-Out-oyslqpxc.ymz --stderr=Microsoft-MIEngine-Error-nzoewxi5.lo3 --pid=Microsoft-MIEngine-Pid-kt3fdbr2.5b2 "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi
a = 2:3:6
b = 0:0:0
重新设置b = 24:20:59
c = 24:20:59

调用析构函数
调用析构函数
调用析构函数


E:\Users\86184\Documents\Code>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-29 21:01:46 | 显示全部楼层
2019年8月29日21:01:11
类的组合
  1. #include <iostream>
  2. #include <cmath>
  3. class dot
  4. {
  5. private:
  6.     int Y, X;

  7. public:
  8.     //构造
  9.     dot(int x = 0, int y = 0) : X(x), Y(y) {}
  10.     //复制构造
  11.     dot(const dot &tdot) : X(tdot.X), Y(tdot.Y) {}
  12.     int getX()
  13.     {
  14.         return X;
  15.     }
  16.     int getY()
  17.     {
  18.         return Y;
  19.     }
  20.     void setdot(int x, int y)
  21.     {
  22.         Y = y;
  23.         X = x;
  24.     }
  25.     void showdot()
  26.     {
  27.         std::cout << "(" << X << " , " << Y << ")" << std::endl;
  28.     }
  29. };
  30. class line
  31. {
  32. private:
  33.     dot Start, End;
  34.     double Length;
  35.    

  36. public:
  37.     line(dot start, dot end) : Start(start), End(end)
  38.     {
  39.         double X = end.getX() - start.getX();
  40.         double Y = end.getY() - start.getY();
  41.         Length = sqrt(pow(X, 2) + pow(Y, 2));
  42.     }
  43.     line(const line &tline) : Start(tline.Start), End(tline.End)
  44.     {
  45.         Length = tline.Length;
  46.     }
  47.     void length()
  48.     {
  49.         std::cout << Length << std::endl;
  50.     }
  51. };
  52. int main(int argc, char const *argv[])
  53. {
  54.     dot start = {5, 9}, end = {9, 20};
  55.     line aline = {start, end};
  56.     aline.length();
  57.     line kline = aline;
  58.     kline.length();
  59.     return 0;
  60. }
复制代码

---------------------------------------------------------------------------------------------------------
Microsoft Windows [版本 10.0.16299.1087]
(c) 2017 Microsoft Corporation。保留所有权利。

E:\Users\86184\Documents\Code>c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.25.0\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-ofgnd5qn.5eu --stdout=Microsoft-MIEngine-Out-2zgryx00.0rd --stderr=Microsoft-MIEngine-Error-rvusglds.1ia --pid=Microsoft-MIEngine-Pid-ww5hv3ry.sbq "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi
11.7047
11.7047


E:\Users\86184\Documents\Code>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-9-4 00:09:42 | 显示全部楼层
本帖最后由 bin554385863 于 2019-9-4 00:14 编辑

2019年9月4日00:09:00
类的继承
  1. #include <iostream>
  2. /*父类*/
  3. class shape
  4. {
  5. protected:
  6.     unsigned int H, L;

  7. public:
  8.     int area()
  9.     {
  10.         return H * L;
  11.     }
  12. };
  13. //子类
  14. class rect : public shape
  15. {
  16. public:
  17.     rect(int l = 0, int h = 0)
  18.     {
  19.         L = l;
  20.         H = h;
  21.     }
  22.     rect(const rect &r)
  23.     {
  24.         L = r.L;
  25.         H = r.H;
  26.     }
  27.     ~rect()
  28.     {
  29.         std::cout << "子类不能使用初值列初始化构造函数" << std::endl;
  30.     };
  31. };
  32. int main(int argc, char const *argv[])
  33. {
  34.     rect r1;
  35.     std::cout <<"r1.area = "<< r1.area() << std::endl;
  36.     rect r2 = {9, 6};
  37.     std::cout <<"r2.area = "<< r2.area() << std::endl;
  38.     return 0;
  39. }
复制代码

-----------------------------------------------------------------------
Microsoft Windows [版本 10.0.16299.1087]
(c) 2017 Microsoft Corporation。保留所有权利。

E:\Users\86184\Documents\Code>c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.25.1\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-eq2d2nqk.0np --stdout=Microsoft-MIEngine-Out-i5vlflfq.qos --stderr=Microsoft-MIEngine-Error-yp3hcvsu.fap --pid=Microsoft-MIEngine-Pid-csr0yko2.w4f "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi
r1.area = 0
r2.area = 54
子类不能使用初值列初始化构造函数
子类不能使用初值列初始化构造函数


E:\Users\86184\Documents\Code>

-----------------------------------------------------------------------------------------------------
---
子类拥有父类的一切非私有数据和函数

---
公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。
保护继承(protected): 当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。
私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。

---
更正:
子类不能使用父类的数据成员用作初值列初始化子类构造函数
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-9-4 23:46:51 | 显示全部楼层
2019年9月4日23:42:54
运算符重载
  1. #include <iostream>
  2. #include <cmath>
  3. class sinx_y
  4. {
  5. private:
  6.     double X;

  7. public:
  8.     sinx_y(double x = 0) : X(x) {}
  9.     sinx_y(const sinx_y &s) : X(s.X) {}
  10.     sinx_y operator+(const sinx_y &y)
  11.     {
  12.         sinx_y result;
  13.         result.X = this->X * sqrt(1 - y.X * y.X) + sqrt(1 - this->X * this->X) * y.X;
  14.         return result;
  15.     }
  16.     sinx_y operator-(const sinx_y &y)
  17.     {
  18.         sinx_y result;
  19.         result.X = this->X * sqrt(1 - y.X * y.X) - sqrt(1 - this->X * this->X) * y.X;
  20.         return result;
  21.     }
  22.     double showresult()
  23.     {
  24.         return X;
  25.     }
  26. };
  27. int main(int argc, char const *argv[])
  28. {
  29.     sinx_y x = 0.5, y = sqrt(3.0) / 2;
  30.     sinx_y z = x + y;
  31.     std::cout << "sin(x+y) = " << z.showresult() << std::endl;
  32.     sinx_y k = y - x;
  33.     std::cout << "sin(x-y) = " << k.showresult() << std::endl;
  34.     return 0;
  35. }

复制代码

-----------------------------------------------------------------------------------------------
Microsoft Windows [版本 10.0.16299.1087]
(c) 2017 Microsoft Corporation。保留所有权利。

E:\Users\86184\Documents\Code>c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.25.1\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-jug5q2wo.xhj --stdout=Microsoft-MIEngine-Out-3r2wfnyi.ee5 --stderr=Microsoft-MIEngine-Error-obkgmcpp.fg3 --pid=Microsoft-MIEngine-Pid-yyvklzxr.whs "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi
sin(x+y) = 1
sin(x-y) = 0.5


E:\Users\86184\Documents\Code>

--------------------------------------------------------------------------------------

  1. 下面是可重载的运算符列表:

  2. +        -        *        /        %        ^
  3. &        |        ~        !        ,        =
  4. <        >        <=        >=        ++        --
  5. <<        >>        ==        !=        &&        ||
  6. +=        -=        /=        %=        ^=        &=
  7. |=        *=        <<=        >>=        []        ()
  8. ->        ->*        new        new []        delete        delete []
  9. 下面是不可重载的运算符列表:

  10. ::        .*        .        ?:
复制代码

重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-9-8 23:35:48 | 显示全部楼层
2019年9月8日23:37:20
虚函数-继承-多态

关注问题:

虚函数的作用
虚函数的实现原理
虚函数表在对象布局里的位置
虚函数的类的sizeof
纯虚函数的作用
多级继承时的虚函数表内容
虚函数如何执行父类代码
多继承时的虚函数表定位,以及对象布局
虚析构函数的作用
虚函数在QT的信号与槽中的应用
虚函数与inline修饰符,static修饰符
前面我们尝试了一个简单的例子,接下来尝试一个多级继承的例子,以及一个多继承的例子。主要涉及到以下问题:多级继承时虚函数表的内容是如何填写的,如何在多级继承的情况下调用某一级父类里的虚函数,以及在多继承(多个父类)的情况下的对象布局。

多级继承
在这里,多级继承指的是有3层或者多层继承关系的情形。让我们看看下面的代码:

多层继承代码示例

//Source filename: Win32Con.cpp
#include <iostream>
using namespace std;
class parent1
{
public:
    virtual int fun1(){cout<<"parent1::fun1()"<<endl;return 0;};
    virtual int fun2()=0;
};
class child1:public parent1
{
public:
    virtual int fun1()
    {
        cout<<"child1::fun1()"<<endl;
        parent1::fun1();
        return 0;
    }
    virtual int fun2()
    {
        cout<<"child1::fun2()"<<endl;
        return 0;
    }
};
class grandson:public child1
{
public:
    virtual int fun2()
    {
        cout<<"grandson::fun2()"<<endl;
        //parent1::fun2();
        parent1::fun1();
        child1::fun2();
        return 0;
    }
};
void test_func1(parent1 *pp)
{
    pp->fun1();
    pp->fun2();
}
int main(int argc, char* argv[])
{
    grandson sunzi;
    test_func1(&sunzi);
    return 0;
}
这段代码展示了三个class,分别是parent1,child1,grandson。

类parent1定义了两个虚函数,其中fun2是一个纯虚函数,这个类是一个不可实例化的抽象基类。
类child1继承了parent1,并且对两个虚函数fun1和fun2都编写了实现的代码,这个类可以被实例化。
类grandson继承了child1,但是只对虚函数fun2编写了实现的代码。
此外,我们还改写了test_func1函数,它的参数为parent1类型的指针,我们可以将parent1的子孙类作为这个函数的参数传入。在这个函数里,我们将依次调用parent1类的两个虚函数。

可以先通过阅读代码预测一下程序的输出内容。

程序的输出内容将是:

child1::fun1()
parent1::fun1()
grandson::fun2()
parent1::fun1()
child1::fun2()
先看第一行输出child1::fun1(),为什么会输出它呢?我们定义的具体对象sunzi是grandson类型的,test_func1的参数类型是parent1类型。在调用这个虚函数的时候,是完成了一次怎样的调用过程呢?

让我们再次使用cl命令输出这几个类的对象布局:

class parent1   size(4):
        +---
0      | {vfptr}
        +---

parent1::$vftable@:
        | &parent1_meta
        |  0
0      | &parent1::fun1
1      | &parent1::fun2

parent1::fun1 this adjustor: 0
parent1::fun2 this adjustor: 0

class child1    size(4):
        +---
        | +--- (base class parent1)
0      | | {vfptr}
        | +---
        +---

child1::$vftable@:
        | &child1_meta
        |  0
0      | &child1::fun1
1      | &child1::fun2

child1::fun1 this adjustor: 0
child1::fun2 this adjustor: 0

class grandson  size(4): //grandson的对象布局
        +---
        | +--- (base class child1)
        | | +--- (base class parent1)
0      | | | {vfptr}
        | | +---
        | +---
        +---

grandson::$vftable@:  //grandson虚函数表的内容
        | &grandson_meta
        |  0
0      | &child1::fun1
1      | &grandson::fun2

grandson::fun2 this adjustor: 0
因为我们实例化的是一个grandson对象,让我们看看它的对象布局。正如前面的例子一样,里面只有一个vfptr指针,但是不一样的却是这个指针所指的虚函数表的内容:

第一个虚函数,填写的是child1类的fun1的地址;第二个虚函数填写的才是grandson类的fun2的地址。

很显然我们可以得出这样一个结论:在一个子对象的虚函数表里,每一个虚函数的实际运行的函数地址,将填写为在继承体系里最后实现该虚函数的函数地址。

所以当我们在test_func1里调用了传入的parent1指针的fun1函数的时候,我们实际执行的是填写在虚函数表里的 child1::fun1(),而调用fun2函数的时候,是从虚函数表里得到了grandson::fun2函数的地址并调用之。在“程序输出结果”表里的第一行和第三行结果证实了上述结论。

再看一下程序代码部分的child1::fun1()的实现代码,在第18行,我们有parent1::fun1();这样的语句,这行代码输出了运行结果里的第二行,而在grandson::fun2()的实现代码第35行的parent1::fun1();以及第36行的child1::fun2();则输出了运行结果里的第四行和第五行的内容。这三行代码展示了如何调用父类以及更高的祖先类里的虚函数。——事实上,这与调用父类的普通函数没有任何区别。

在程序代码的第34行,有一行被注释了的内容//parent1::fun2();,之所以会注释掉,是因为这样的代码是无法通过编译的,因为在parent1类里,fun2是一个“纯虚函数”也就是说这个函数没有代码实体,在编译的时候,链接器将无法找到fun2的目标代码从而报错。

其实有了对虚函数的正确的认识,上面的多级继承是很自然就能明白的。然而在多继承的情况下,情况就有所不同了。。。

多继承下虚函数的使用
假如一个类,它由多个父类继承而来,而在不同的父类的继承体系里,都存在虚函数的时候,这个类的对象布局又会是怎样的?它又是怎样定位虚函数的呢?

让我们看看下面的代码:

程序输出结果

//Source filename: Win32Con.cpp
#include <iostream>
using namespace std;
class parent1
{
public:
    virtual int fun1(){cout<<"parent1::fun1()"<<endl;return 0;};
};
class parent2
{
public:
    virtual int fun2(){cout<<"parent2::fun2()"<<endl;return 0;};
};
class child1:public parent1,public parent2
{
public:
    virtual int fun1()
    {
        cout<<"child1::fun1()"<<endl;
        return 0;
    }
    virtual int fun2()
    {
        cout<<"child1::fun2()"<<endl;
        return 0;
    }
};
void test_func1(parent1 *pp)
{
    pp->fun1();
}
void test_func2(parent2 *pp)
{
    pp->fun2();
}
int main(int argc, char* argv[])
{
    child1 chobj;
    test_func1(&chobj);
    test_func2(&chobj);
    return 0;
}
这一次,我们有两个父类,parent1和parent2,在parent1里定义了虚函数fun1,而在parent2里定义了虚函数fun2,然后我们有一个子类child1,在里面重新实现了fun1和 fun2两个虚函数。然后我们编写了test_func1函数来调用parent1类型对象的fun1函数,编写了test_func2函数调用 parent2对象的fun2函数。在main函数里我们实例化了一个child1类型的对象chobj,然后分别传给test_func1和 test_func2去执行。

这段代码的运行结果非常简单就能看出来:

child1::fun1()

child1::fun2()

但是,让我们看看对象布局吧:

class child1    size(8):
        +---
        | +--- (base class parent1)
0      | | {vfptr}
        | +---
        | +--- (base class parent2)
4      | | {vfptr}
        | +---
        +---

child1::$vftable@parent1@:
        | &child1_meta
        |  0
0      | &child1::fun1

child1::$vftable@parent2@:
        | -4
0      | &child1::fun2

child1::fun1 this adjustor: 0
child1::fun2 this adjustor: 4
注意到没?在child1的对象布局里,出现了两个vfptr指针!

这两个虚函数表指针分别继承于parent1和parent2类,分别指向了不同的两个虚函数表。

问题来了,当我们使用test_func1调用parent1类的fun1函数的时候,调用个过程还比较好理解,可以从传入的地址参数取得继承自 parent1的vfptr,从而执行正确的fun1函数代码,但是当我们调用test_func2函数的时候,为什么程序可以自动取得来自 parent2的vfptr呢,从而得出正确的fun2函数的地址呢?

其实,这个工作是编译器自动根据实例的类型完成的,在编译阶段就已经确定了在调用test_func2的时候,传入的this指针需要增加一定的偏移(在这里则是第一个vfptr所占用的大小,也就是4字节)。

我们可以看看main函数里这部分代码的反汇编代码:

反汇编代码

    child1 chobj;
00F5162E 8D 4D F4         lea         ecx,[chobj]
00F51631 E8 F5 FB FF FF   call        child1::child1 (0F5122Bh)
    test_func1(&chobj);
00F51636 8D 45 F4         lea         eax,[chobj]
00F51639 50               push        eax  
00F5163A E8 6F FB FF FF   call        test_func1 (0F511AEh)
00F5163F 83 C4 04         add         esp,4
    test_func2(&chobj);
00F51642 8D 45 F4         lea         eax,[chobj]
00F51645 85 C0            test        eax,eax
00F51647 74 0E            je          main+47h (0F51657h)
00F51649 8D 4D F4         lea         ecx,[chobj]
00F5164C 83 C1 04         add         ecx,4
00F5164F 89 8D 2C FF FF FF mov         dword ptr [ebp-0D4h],ecx
00F51655 EB 0A            jmp         main+51h (0F51661h)
00F51657 C7 85 2C FF FF FF 00 00 00 00 mov         dword ptr [ebp-0D4h],0
00F51661 8B 95 2C FF FF FF mov         edx,dword ptr [ebp-0D4h]
00F51667 52               push        edx  
00F51668 E8 F6 FA FF FF   call        test_func2 (0F51163h)
00F5166D 83 C4 04         add         esp,4
    return 0;
从第4行至第5行,执行的是test_func1函数,this指针指向 chobj (第2行lea ecx,[chobj]),但是调用test_func2函数的时候,this指针被增加了4(第14行)!于是,在test_func2执行的时候,就可以从&chobj+4的地方获得vfptr指针,从而根据parent2的对象布局得到了fun2的地址并执行了。

为了证实这点,我们可以将代码做如下的修改:

1:  int main(int argc, char* argv[])
2:  {
3:      child1 chobj;
4:      test_func1(&chobj);
5:      test_func2((parent2 *)(void *)&chobj);
6:      return 0;
7:  }
8:  
请注意红色部分的变化,在讲chobj传入给test_func2之前,先用(void *)强制转换为无类型指针,再转换为parent2 指针,这样的转换,显然是可行的,因为chobj本身就是parent2的子类,然而,程序的执行效果却是:

child1::fun1()

child1::fun1()

执行test_func2函数,调用的是parent2::fun2,但是居然执行的是child1::fun1()函数!!!

这中间发生了些什么呢?我们再看看反汇编的代码:

反汇编的代码

    child1 chobj;
013D162E 8D 4D F4         lea         ecx,[chobj]
013D1631 E8 F5 FB FF FF   call        child1::child1 (13D122Bh)
    test_func1(&chobj);
013D1636 8D 45 F4         lea         eax,[chobj]
013D1639 50               push        eax  
013D163A E8 6F FB FF FF   call        test_func1 (13D11AEh)
013D163F 83 C4 04         add         esp,4
    test_func2((parent2*)(void *)&chobj);
013D1642 8D 45 F4         lea         eax,[chobj]
013D1645 50               push        eax  
013D1646 E8 18 FB FF FF   call        test_func2 (13D1163h)
013D164B 83 C4 04         add         esp,4
    return 0;
从调用test_func2的反汇编代码可以看到,这一次ecx寄存器的值没有做改变!所以在执行test_func2的时候,将取得 parent1对象布局里的vfptr,而这个vfptr所指的虚函数表里的第一项就是fun1,并且被填写为child1::fun1的地址了。所以才出现了child::fun1的输出内容!显然这里有一个隐藏的致命问题,加入parent1和parent2的第一个虚函数的参数列表不一致,这样的调用显然就会导致堆栈被破坏掉,程序99%会立即崩溃。之前的程序没有崩溃并且成功输出内容,不过是因为parent1::fun1()和 parent2::fun2()的参数列表一致的关系而已。
所以,千万不要在使用一个多继承对象的时候,将其类型信息丢弃,编译器还需要依靠正确的类型信息,在使用虚函数的时候来得到正确的汇编代码!

多继承与虚函数重复
既然说到了多继承,那么还有一个问题可能会需要解决,那就是如果两个父类里都有相同的虚函数定义,在子对象的布局里会是怎么样个情况?是否依然可以将这个虚函数指向到正确的实现代码上呢?

修改前面一个源代码,在parent2的接口里增加下面的虚函数定义:

virtual int fun1(){cout<<"parent2::fun1()"<<endl;return 0;};
上面的fun1的定义与parent1类里的完全重复相同(类型,参数列表),增加上面的代码后立即开始编译,程序正常编译通过。运行之,得到下面的结果:

child1::fun1()

child1::fun2()

这个程序居然正确的完成了执行,编译器在其中做了些怎样的工作,是怎么样避免掉队fun1函数的冲突问题呢?

让我们来看看这个时候的child1的对象布局:

class child1    size(8):
        +---
        | +--- (base class parent1)
0      | | {vfptr}
        | +---
        | +--- (base class parent2)
4      | | {vfptr}
        | +---
        +---

child1::$vftable@parent1@:
        | &child1_meta
        |  0
0      | &child1::fun1

child1::$vftable@parent2@:
        | -4
0      | &child1::fun2
1      | &thunk: this-=4; goto child1::fun1

child1::fun1 this adjustor: 0
child1::fun2 this adjustor: 4
恩~~~还是两个vfptr在child1的对象布局里(不一样就怪啦,呵呵),但是第二个vfptr所指的虚函数表的内容有所变化哦!

注意看红色字体部分,虚函数表里并没有直接填写child::fun1的代码,而是多了一个 &thunk: this-=4;然后才goto child1::fun1!注意到一个关键名词thunk了吧?没错,vc在这里使用了名为thunk的技术,避免了虚函数fun1在两个基类里重复出现导致的冲突问题!(除了thunk,还有其他方法可以解决此类问题的)。

现在,我们知道为什么相同的虚函数不会在子类里出现冲突的情况了。

但是,倘若我们在基类里就是由两个冲突的普通函数,而不是虚函数,是个怎样的情况呢?

多继承产生的冲突与虚继承,虚基类
我们在parent1和parent2里添加一个相同的函数void fun3(),然后再进行编译,通过了!查看类对象布局,跟上面的完全一致。但是在main函数里调用chobj.fun3()的时候,编译器却不再能正确编译了,并且会提示“error C2385: 对“fun3”的访问不明确”的错误信息,没错,编译器不知道你要访问哪个fun3了。

如何解决这样的多继承带来的问题呢,其实有一个简单的做法。就是在方法前限定引用的具体是哪个类的函数,比如:chobj.parent1::fun3();  ,这样的写法就写明了是要调用chobj的父类parent1里的fun3()函数!

我们再看看另外一种情况,从parent1和parent2里抹去刚才添加的fun3函数,将之放到一个共同的基类里:

class commonbase
{
public:
    void fun3(){cout<<"commonbase::fun3()"<<endl;}
};
而parent1和parent2都修改为从此类继承。可以看到,在这个情况下,依然需要使用chobj.parent1::fun3();  的方式才可以正确调用到fun3,难道,在这种情况下,就不能自然的使用chobj.fun3()这样的方式了吗?

虚继承可以解决这个问题——我们在parent1和parent2继承common类的地方添加上一个关键词virtual,如下:

class parent1:virtual public commonbase
{
public:
    virtual int fun1(){cout<<"parent1::fun1()"<<endl;return 0;};
};
给parent2也同样的处理,然后再次编译,这次chobj.fun3()可以编译通过了!!!

编译器这次又在私下里做了哪些工作了呢????

class child1    size(16):
        +---
        | +--- (base class parent1)
0      | | {vfptr}
4      | | {vbptr}
        | +---
        | +--- (base class parent2)
8      | | {vfptr}
12      | | {vbptr}
        | +---
        +---
        +--- (virtual base commonbase)
        +---

child1::$vftable@parent1@:
        | &child1_meta
        |  0
0      | &child1::fun1

child1::$vftable@parent2@:
        | -8
0      | &child1::fun2
1      | &thunk: this-=8; goto child1::fun1

child1::$vbtable@parent1@:
0      | -4
1      | 12 (child1d(parent1+4)commonbase)

child1::$vbtable@parent2@:
0      | -4
1      | 4 (child1d(parent2+4)commonbase)

child1::fun1 this adjustor: 0
child1::fun2 this adjustor: 8

vbi:       class  offset o.vbptr  o.vbte fVtorDisp
      commonbase      16       4       4 0
这次变化可大了去了!!!

首先,可以看到两个类parent1和parent2的对象布局里,都多了一个vbptr的指针。而在child1的对象布局里,还有一个virtual base commonbase的虚拟基类。再看看两个vbptr的内容:

12 (child1d(parent1+4)commonbase) 这个很好理解,从parent1的vbptr开始,偏移12个字节,指向的是virtual base commonbase!

再看看4 (child1d(parent2+4)commonbase) ,从parent2的vbptr开始,便宜4个字节,也指向了virtual base commonbase!

这下明白了。虚基类在child1里只有一个共同的对象布局了,所以就可以直接用chobj.fun3()啦,当然,在commonbase里的其他成员变量此时也可以同样的方式访问了!

虽然解决方案有了,但是在一个系统的设计里,如果有一个基类出现多继承冲突的情况,大部分情况下都说明这样的设计是有问题的,应该尽量避免这样的设计,并且尽量用纯虚函数,来提取一些抽象的接口类,把共同的方法接口都抽取出来,通常就能避免多继承的问题。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-9-10 18:49:34 | 显示全部楼层
本帖最后由 bin554385863 于 2019-9-10 22:51 编辑

2019年9月10日18:43:35
.组合
类的成员中出现其他类的对象,叫做类的组合.

.继承

.虚继承:
父类:A;
子类B , C继承于A;
子类D继承于B, C;
则B, C, 需要使用虚继承,避免D中出现重复的A.

class A {...}
class B: virtual public A {...}
class C: virtual public A {...}
class D: public B, public C {...}


.虚函数
当多个子类需要改写父类的成员函数时, 父类中对应的成员函数需要声明为虚函数

.虚函数的特点
关于虚函数的特点:
(1)要有子类公有继承父类,虚函数才有意义
(2)子类重写的父类的虚函数也是虚函数(类Dog中的eat函数是虚函数),只不过省略了关键字virtual
(3)虚函数必须是所在类的成员函数,而不能是友元函数或静态函数。因为虚函数调用要靠特定的对象来决定激活哪一个函数。
(4)构造函数不能是虚函数,原因是构造函数在创建时首先被调用,也就是说在编译时就要把构造函数的地址绑定好。而析构函数可以是虚函数,因为析构函数最后调用,可以在运行时动态匹配。

基类定义了虚函数, 并且是public的,那么子类只要override 虚函数 无论放在什么样的访问权限下(private,protect,public), 都以基类的访问权限为准, 即是public的。


.虚析构
把析构函数设为虚函数主要是为了防止内存泄漏
我们首先要知道的事实(单继承时):
构造函数的调用顺序:从当前类往上找父类,一直找到最上层的父类,我们可以理解为始祖,它是最先构造的,然后沿着继承路径依次往下构造,一直到当前类。
析构函数的调用顺序:从当前类开始析构,析构完再沿着继承路径往上找父类 ,析构父类 ,再找到最上层的父类 析构

.虚函数的默认参数
虚函数是动态绑定的,而虚函数的默认参数是静态绑定的,因此在编译时已经把虚函数的参数的值确定了,而不管在后面执行时动态调用哪个虚函数改变的值

  1. #include <iostream>
  2. using namespace std;

  3. class A
  4. {
  5. public:
  6.     A()
  7.     {
  8.         cout << "A的构造函数" << endl;
  9.     }
  10.     ~A()
  11.     {
  12.         cout << "A的析构函数" << endl;
  13.     }
  14. };

  15. class B:public A
  16. {
  17. public:
  18.     B()
  19.     {
  20.         p = new char[20];
  21.         cout << "B的构造函数" << endl;
  22.     }
  23.     ~B()
  24.     {
  25.         if (p != NULL)
  26.             delete[] p;
  27.         cout << "B的析构函数" << endl;
  28.     }

  29. private:
  30.     char *p;
  31. };

  32. void func(A *pa)
  33. {
  34.     delete pa;
  35. }


  36. int main()
  37. {
  38.     A *pa = new B;      //构造函数被调用两次,A先B后
  39.     func(pa);           //析构函数只被调用一次,A调用

  40.     return 0;
  41. }
复制代码

----------------------------------------------------------------------
————————————————
版权声明:本文为CSDN博主「qq_1061856980華仔」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hua12134/article/details/79780419

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-9-11 00:55:38 | 显示全部楼层
本帖最后由 bin554385863 于 2019-9-11 11:27 编辑

2019年9月11日00:55:53
虚函数,虚继承
  1. #include <iostream>
  2. class animal
  3. {
  4. public:
  5.     animal()
  6.     {
  7.         std::cout << "父类构造" << std::endl;
  8.     }
  9.     void eat()
  10.     {
  11.         std::cout << "父类成员函数eat()" << std::endl;
  12.     }
  13.     virtual void sleep()
  14.     {
  15.         std::cout << "父类成员函数sleep()" << std::endl;
  16.     }
  17.     virtual ~animal()
  18.     {
  19.         std::cout << "父类析构函数" << std::endl;
  20.     }
  21. };
  22. class dog : virtual public animal
  23. {
  24. public:
  25.     dog()
  26.     {
  27.         std::cout << "子类dog构造函数" << std::endl;
  28.     }
  29.     virtual void sleep()
  30.     {
  31.         std::cout << "子类dog成员函数sleep()" << std::endl;
  32.     }
  33.     virtual ~dog()
  34.     {
  35.         std::cout << "子类dog析构函数" << std::endl;
  36.     }
  37. };
  38. class pig : virtual public animal
  39. {
  40. public:
  41.     pig()
  42.     {
  43.         std::cout << "子类pig构造函数" << std::endl;
  44.     }
  45.     virtual void sleep()
  46.     {
  47.         std::cout << "子类pig成员函数sleep()" << std::endl;
  48.     }
  49.     virtual ~pig()
  50.     {
  51.         std::cout << "子类pig析构函数" << std::endl;
  52.     }
  53. };
  54. class ppg : public dog, public pig
  55. {
  56. public:
  57.     ppg()
  58.     {
  59.         std::cout << "ppg构造函数" << std::endl;
  60.     }
  61.     virtual void sleep()
  62.     {
  63.         std::cout << "ppg成员函数sleep()" << std::endl;
  64.     }
  65.     virtual ~ppg()
  66.     {
  67.         std::cout << "ppg析构函数" << std::endl;
  68.     }
  69. };
  70. int main(int argc, char const *argv[])
  71. {
  72.     ppg p;
  73.     animal *ppg = &p;
  74.     ppg->sleep();
  75.     ppg->eat();
  76.     return 0;
  77. }
复制代码

---------------------------------------------------------------------------------------------------------------
Microsoft Windows [版本 10.0.16299.1087]
(c) 2017 Microsoft Corporation。保留所有权利。

E:\Users\86184\Documents\Code>c:\Users\86184\.vscode\extensions\ms-vscode.cpptools-0.25.1\debugAdapters\bin\WindowsDebugLauncher.exe --stdin=Microsoft-MIEngine-In-2i0pz4rl.ub2 --stdout=Microsoft-MIEngine-Out-1z1pnj4a.tq0 --stderr=Microsoft-MIEngine-Error-5ykprrfo.1a2 --pid=Microsoft-MIEngine-Pid-ievsqwkx.vhs "--dbgExe=E:\My Program\MinGW\bin\gdb.exe" --interpreter=mi
父类构造
子类dog构造函数
子类pig构造函数
ppg构造函数

ppg成员函数sleep()
父类成员函数eat()

ppg析构函数
子类pig析构函数
子类dog析构函数
父类析构函数


E:\Users\86184\Documents\Code>
-----------------------------------------------------------------------
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-12 14:50

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表