文章目录
- 成员函数(方法)
- 示例1:在结构体中引入成员函数
- 示例2:类
- 示例3:类内定义成员函数
- 示例4:类内声明+类外定义显示内敛的成员函数
- 示例5:类内声明+类外定义成员函数
- 示例6:类与编译期的两遍处理
- 示例7:成员函数与尾随返回类型
- 示例8:使用 this 指针引用当前对象
- 示例9:基于 const 的成员函数
- 补充示例:基于 const 的成员函数重载
- 示例10:成员函数的名称查找与隐藏关系
- 示例11:在静态成员函数中返回静态数据成员
- 示例12:成员函数基于引用限定符的重载
成员函数(方法)
● 可以在结构体中定义函数,作为其成员的一部分:对内操作数据成员,对外提供调用接口
– 在结构体中将数据与相关的成员函数组合在一起将形成类,是 C++ 在 C 基础上引入的概念
– 关键字 class
– 类可视为一种抽象数据类型,通过相应的接口(成员函数)进行交互
– 类本身形成域,称为类域
● 成员函数的声明与定义
了解内联:什么是内联、隐式内联和显式内联
– 类内定义(隐式内联)
– 类内声明 + 类外定义
注意:类内定义的成员函数为内联函数;类内声明 + 类外定义的成员函数默认为费内敛函数,也显示定义为内敛函数。
– 类与编译期的两遍处理
– 成员函数与尾随返回类型( trail returning type )
● 成员函数与 this 指针
– 使用 this 指针引用当前对象
– 基于 const 的成员函数重载
● 成员函数的名称查找与隐藏关系
– 函数内部(包括形参名称)隐藏函数外部
– 类内部名称隐藏类外部
– 使用 this 或域操作符引入依赖型名称查找
● 静态成员函数
– 在静态成员函数中返回静态数据成员
● 成员函数基于引用限定符的重载( C++11 )
示例1:在结构体中引入成员函数
#include <iostream>
struct myStr
{
int x = 3;
void print()
{
std::cout << x << std::endl;
}
};
int main()
{
myStr str;
str.print();
}
输出:
3
示例2:类
#include <iostream>
class myStr
{
public:
int x = 3;
void print()
{
std::cout << x << std::endl;
}
};
int main()
{
myStr str;
str.print();
}
输出:
3
结构体与类区别:结构体默认public,而class默认private
示例3:类内定义成员函数
其中,函数void print()
属于类内定义的隐式内联函数。
#include <iostream>
class myStr
{
public:
int x = 3;
void print()
{
std::cout << x << std::endl;
}
};
int main(int argc, char* argv[])
{
myStr str;
str.print();
}
输出:
3
示例4:类内声明+类外定义显示内敛的成员函数
header.h
内类声明
#pragma once
#include <iostream>
class myStr
{
public:
int x = 3;
void print();
};
inline void myStr::print()
{
std::cout << x << std::endl;
}
main.cpp
调用
#include "header.h"
int main(int argc, char* argv[])
{
myStr str;
str.print();
}
示例5:类内声明+类外定义成员函数
header.h
内类声明
#pragma once
#include <iostream>
class myStr
{
public:
int x = 3;
void print();
};
source.cpp
类外定义
#include "header.h"
void myStr::print()
{
std::cout << x << std::endl;
}
main.cpp
调用
#include "header.h"
int main(int argc, char* argv[])
{
myStr str;
str.print();
}
示例6:类与编译期的两遍处理
将header.h
头文件改写为
#pragma once
#include <iostream>
class myStr
{
public:
void print()
{
std::cout << x << std::endl;
}
int x = 3;
};
main.cpp
调用
#include "header.h"
int main(int argc, char* argv[])
{
myStr str;
str.print();
}
当程序执行到header.h
头文件第7行,理论上应该会报错,因为print()中x没有声明。之所以不报错,是由于编译器(编译期的两遍处理)第一遍处理函数和数据,但不处理函数内部的内容,第二次再处理函数内部内容。
示例7:成员函数与尾随返回类型
header.h
内类声明
#pragma once
#include <iostream>
class myStr
{
public:
using myInt = int;
myInt x = 3;
myInt Add();
};
source.cpp
类外定义
#include "header.h"
auto myStr::Add()->myInt
{
return x + 1;
}
main.cpp
调用
#include "header.h"
int main(int argc, char* argv[])
{
myStr str;
std::cout << str.Add() << std::endl;
}
}
输出:
4
示例8:使用 this 指针引用当前对象
将header.h
头文件写为
#pragma once
#include <iostream>
class myStr
{
public:
void print()
{
std::cout << this << std::endl;
std::cout << this->x << std::endl;
}
int x = 0;
};
main.cpp
调用
#include "header.h"
int main(int argc, char* argv[])
{
myStr str1;
str1.x = 3;
std::cout << (&str1) << std::endl;
str1.print();
myStr str2;
str2.x = 8;
std::cout << (&str2) << std::endl;
str2.print();
}
输出:
000000DF499FFB44
000000DF499FFB44
3
000000DF499FFB64
000000DF499FFB64
8
补充示例:
将header.h
头文件写为
#pragma once
#include <iostream>
class myStr
{
public:
void print(int x)
{
std::cout << x << std::endl;
std::cout << this->x << std::endl;
}
int x = 0;
};
main.cpp
调用
#include "header.h"
int main(int argc, char* argv[])
{
myStr str1;
str1.print(8);
}
输出:
8
0
示例9:基于 const 的成员函数
将header.h
头文件写为
#pragma once
#include <iostream>
class myStr
{
public:
void print( ) const
{
std::cout << this->x << std::endl;
}
int x = 0;
};
main.cpp
调用
#include "header.h"
int main(int argc, char* argv[])
{
myStr str1;
str1.print();
}
输出:
0
补充示例:基于 const 的成员函数重载
将header.h
头文件写为
#pragma once
#include <iostream>
class myStr
{
public:
void print()
{
}
void print() const
{
}
int x = 0;
};
main.cpp
调用
#include "header.h"
int main(int argc, char* argv[])
{
myStr str1;
str1.print();
}
通过这个例子,了解const成员函数重载。
示例10:成员函数的名称查找与隐藏关系
成员函数的名称查找优先级:
函数内部(包括形参名称)-> 类内部名称 -> 类外部名称
意思很简单,就是如果成员函数内部存在x,则使用该x;若成员函数内部不存在x,则使用类内部名称;若成员函数内部与类内部名称都不存在x,则使用类外部定义的x。
将header.h
头文件写为
#pragma once
#include <iostream>
int x = 2;
class myStr
{
public:
void print()
{
int x = 0;
std::cout << x << std::endl;
std::cout << this->x << std::endl;
std::cout << ::x << std::endl;
}
int x = 1;
};
main.cpp
调用
#include "header.h"
int main(int argc, char* argv[])
{
myStr str1;
str1.print();
}
输出:
0
1
2
示例11:在静态成员函数中返回静态数据成员
了解C/C++ 中 static 的用法全局变量与局部变量 | 菜鸟教程 (runoob.com)
将header.h
头文件写为
#pragma once
#include <iostream>
class myStr
{
public:
myStr()
{
x++;
y += x;
}
static void print()
{
std::cout << x << std::endl;
}
static int gety()
{
return y;
}
static int x;
static int y;
};
int myStr::x = 0;
int myStr::y = 0;
main.cpp
调用
#include "header.h"
int main(int argc, char* argv[])
{
myStr str1;
myStr::print();
myStr str2;
myStr::print();
std::cout << myStr::gety() << std::endl;
}
输出:
1
2
3
示例12:成员函数基于引用限定符的重载
将header.h
头文件写为
#pragma once
#include <iostream>
class myStr
{
public:
void print() &
{
}
void print() &&
{
}
void print() const &
{
}
void print() const &&
{
}
};
main.cpp
调用
#include "header.h"
int main(int argc, char* argv[])
{
myStr str1;
str1.print();
myStr().print();
}
参考资料:
《C++ Primer 中文版》(第 5 版)
《C++基础与深度解析》深蓝学院课程
非静态成员函数 - cppreference.com
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)