广州大型网站建设,手机端百度收录入口,html在线编写网站,网站建设准备工作总结C类
1. 类内成员函数隐式声明为inline
class Str {int x;int y 3;
public:inline void fun(){std::coutpf,yes!std::endl;}
};这段代码不会报错#xff0c;但是类内的成员函数隐式声明为inline函数#xff0c;不需要单独写在前面。因此将成员…C类
1. 类内成员函数隐式声明为inline
class Str {int x;int y 3;
public:inline void fun(){std::coutpf,yes!std::endl;}
};这段代码不会报错但是类内的成员函数隐式声明为inline函数不需要单独写在前面。因此将成员函数在类的内部实现是最保险的写法。
2. 全局函数上使用inline。
inline int Add(int x, int y) {return x y;
}这是全局函数上使用inline函数。
同样上述代码可以写在头文件之中或写在源文件之中如果不使用 inline那么写在头文件之中被多个源文件 include 那么就会导致符号重定义冲突单个源文件引入却不会。
3. inline关键字的作用 可以在任意的函数定义的时候使用 建议编译器使用内嵌的方式优化代码 inline函数由调用的函数的源文件实现
使用使用内联展开取决于函数的复杂程度
以下的函数使用inline也不会被优化
1、函数指针或函数引用
2、复杂的 inline 函数体
3、虚函数
4、递归函数
举例说明如下
头文件中
#ifndef ICPP_HEADER_H
#define ICPP_HEADER_H
#include iostream
using namespace std;
class Str {int x;int y 3;
public:void fun() {cout yes pf endl;}
};#endif //ICPP_HEADER_H
main文件中
#include header.h
#include iostream
using namespace std;int main() {int a 0;int c a 7;Str str;str.fun();std::cout Hello, World! std::endl;return 0;
}另外一个源文件中这样写
#include header.h
#include iostream编译成功
但是如果头文件中类内声明类外定义就会报错。
#ifndef ICPP_HEADER_H
#define ICPP_HEADER_H#include iostream
using namespace std;
class Str {int x;int y 3;
public:void fun();
};void Str::fun() {cout yes pf endl;}
#endif //ICPP_HEADER_H
报错信息如下
/mnt/e/iCode/icpp/header.h:17: multiple definition of Str::fun(); CMakeFiles/icpp.dir/main.cpp.o:/mnt/e/iCode/icpp/header.h:17: first defined here
collect2: error: ld returned 1 exit status问题分析
关于函数的声明和定义可以写在头文件之中也可以写在源文件之中但如果不加inline那么写在头文件之中被多个源文件 include 那么就会导致符号重定义冲突单个源文件引入却不会。 如果仅有一个头文件一个文件使用头文件中的类的外部定义不会出现问题类内定义和实现函数不论有多少外部使用这个头文件的源文件都不会报错多文件使用头文件时类内声明类外定义将类外的定义声明成内联函数使用inline关键字不会报错掌握inline关键字的使用方法 4. 分析下面几种写法
回答以下几个问题 这个使用方法using my_int int 类外声明的使用的使用方法最好使用下面这种写法 inline auto Str::fun2()-my_int {{coutmy_intendl;}
}举例如下
//
// Created by pfw20 on 2024/3/31.
//#ifndef ICPP_HEADER_H
#define ICPP_HEADER_H#include iostream
using namespace std;
class Str {using my_int int;my_int m;int x;int y 3;
public:void fun();my_int fun1();my_int fun2();
};inline Str::my_int Str::fun1() {{coutmy_intendl;}
}
// 简化上述的代码另外一种写法
inline auto Str::fun2()-my_int {{coutmy_intendl;}
}inline int Add(int x, int y) {return x y;
}
inline void Str::fun() {cout yes pf endl;}
#endif //ICPP_HEADER_H
待说明
\#includeiostream\#includelimitsstruct A{// char a a;int c 10;};int main(){int x 10;char y a;std::coutstd::numeric_limitsint::min()std::endl;std::coutsizeof(A)std::endl;std::coutalignof(int) std::endl;}5. this指针指向当前对象
在类的内部会有一个this指针类型为class* this 隐藏指针this 是一个常量指针不能修改指针指向的内容是可以修改。
修改类的成员所以可以使用this-成员访问类内的成员
用处
使用this可以防止函数中的参数和类中的成员混淆基于const的成员函数重载 class Str{void fun(int x){}
// 基于const的成员函数重载void fun(int x) const{ // this 本身不能修改可以修改指向的内容加上const之后指向的内容也是不能修改的。}int x;
};基于引用的重载不作重点记录
这个和基于const的重载不能混淆使用。仅仅使用const或者仅仅使用引用
多个相同的变量出现在类的内部和全局中使用类内部的可以使用this指针全局的使用即可
静态成员函数
所有的对象共享这个成员函数每一个对象有自己的对象成员不会出现交叉
静态成员就没有this指针使用这个成员可以使用类的操作域进行访问这个静态成员。
这个就可以将全局的常量定义为static的格式。
用处
描述和类相关参数和对象无关静态成员函数可以返回静态数据成员静态成员函数操作静态成员
单例模式
class Str{static auto size(){static Str x;return x;}} 6. 报错原因分析
为什么直接报错/mnt/e/iCode/icpp/main.cpp:18: undefined reference to Str1::x’
#include iostream
class Str1{
public:static int x;int y;};
int main(){std::coutStr1::xstd::endl;
}修改如下运行成功
#include iostream
class Str1{
public:inline static int x;int y;
};
int main(){std::coutStr1::xstd::endl;// 输出0
}C特性封装举例子洗衣机的电路板
7. C特殊的成员函数
构造函数
代理构造函数
构造函数是可以重载的
C11的代理构造函数代理构造函数先执行
代理构造函数如下基本不使用仅仅了解即可
\#include iostream
class Strp{
public:Strp():Strp(10){std::couthere1std::endl;}Strp(int input){x input;std::couthere2std::endl;}
private:int x;
};int main(){Strp strp1;
}
构造函数初始化重要
初始化列表不使用缺省初始化
区分数据成员的初始化和赋值
在构造的时候通过列表初始化完成提升系统的性能
#include iostream
#include stringclass Strp {
public:Strp(const std::string val) : x(val), y(0) {std::coutxstd::endl;}private:std::string x;int y;
};int main() {Strp strp1(pf);
}类中包含引用的成员此时必须使用列表进行初始化
#include iostream
#include stringclass Strp {
public:Strp(const std::string val,int ref_i): x(val), y(0),ref(ref_i) {std::coutxstd::endl;ref 2;}private:std::string x;int y;int ref;
};int main() {int val;Strp strp1(pf,val);
}元素的初始化顺序与其声明的顺序有关与初始化列表中的顺序无关 要求在初始化化列表时顺序要一致这里的一致就是先声明的先进行初始化否则会包warnning 使用初始化列表覆盖类的内部的初始化信息
缺省的构造函数 不提供实参的构造函数 如果没有定义构造函数编译器会提供一个缺省的构造函数目的和C语言兼容如果写一个就不会合成如果类的成员中有引用成员引用必须显示初始化。 缺省的构造函数会缺省构造函数进行缺省初始化。 调用缺省的构造函数避免most vexing parse 使用default定义和内部的缺省的构造函数是一样的
举例子说明如下
报错
#include iostream
#include stringclass Strp {
public:
// Strp() default;Strp(const std::string input) : x(input) {}std::string x;
};int main() {
Strp s;
}No matching constructor for initialization of ‘Strp’
#include iostream
#include stringclass Strp {
public:Strp() default;Strp(const std::string input) : x(input) {}std::string x;
};int main() {
Strp s;
}不再进行报错
或者下面这样写也不会报错
#include iostream
#include stringclass Strp {
public:Strp(){}Strp(const std::string input) : x(input) {}std::string x;
};int main() {
Strp s;
}单一的参数构造函数 可以将其看成是一种类型转换 可以使用explicit关键字避免求值过程中的隐式转换 #include iostream
#include stringclass Myclass {
public:
// explicit Myclass(const int input): x(input) {}int x;
};int main() {Myclass my(3);// 直接参数列表进行初始化Myclass m1 3;// // 拷贝初始化涉及到类型的隐式转换避免隐式转换使用explicit进行标注Myclass m2{3};Myclass m3(Myclass(3));}拷贝的构造函数重要
原有的对象来构造一个新的构造函数
不希望改变值不能使用值传递原因是会进行嵌套死循环
拷贝构造函数的经典写法如果没有显示提供拷贝构造函数编译器会自动生成一个对每一个数据成员调用拷贝构造
#include iostream
#include stringclass Myclass {
public:
// explicit // 全部考虑是引用传递引用是对值的绑定
// 单一参数的构造函数Myclass(const int input) : x(input) {}// 缺省的构造函数Myclass() default;// 拷贝的构造函数的经典写法为什么是const为什么是引用
// Myclass(const Myclass) default;Myclass(const Myclass m) : x(m.x) {// 这个也可以使用default}int x 4;
};int main() {Myclass my(3);// 直接参数列表进行初始化Myclass m1 3;// // 拷贝初始化涉及到类型的隐式转换避免隐式转换使用explicit进行标注Myclass m2{3};Myclass m3(Myclass(3));}移动构造函数待更新