c++函数
来自一个小白期中考试前对函数的总结
内容:
- 函数体 ,如函数的调用;
- 函数的输入输出,如结构体和数组 ;
- 多态,如重载、虚函数;
- 其他,如友员函数;
- 常用函数,如compare(); ;
1.函数体
···
//定义函数
void stars(void);
//return receive
/*或者直接定义
void stars(void){
cout<<"hello world";
}*/
main(){
stars() //调用函数
}
void stars(void){
cout<<"hello world";
}
参数:
形参与实参:
形参:函数内使用的变量;
实参:函数接收的参数(调用时括号内的数值)
按值传参:
void any_function(int p);
//传入的是副本,函数内对p修改不会导致函数外的改变;
按引用传参:
void any_function(int & p);
//传入的是地址,函数内对p修改会导致函数外的改变;
默认值:
void disp_chars(int num=1;char ch=' ');
内联函数:
inline int minimun ( int num1 , int num2 );
可减小调用函数的花费时间,一般在函数只有1~3行时使用;
储存类型:
auto:不声明时变量默认为auto型,在函数结束后被释放;
int auto_num = 0;
// auto int auto_num = 0;
static:只分配一次储存空间,函数结束不异其值;
static int static_num = 0;
2.函数的输入输出
数组:
输入:
···
int Input (long num[], float score[], int array_size);
//二维:int Input (long num[], float score[][3], int array_size);
int main(){
int array_size=0;
long num[N];
float score[N];
array_size= Input ( num, score, array_size);
···
}
···
输出:
数组输入的本来就是地址,所以无需特意输出;即在函数内编辑数组,函数外的数组也会自动改变;
结构体:
输入:
···
sturct student{
int number;
float score[5];
}
void get_data ( sturct student student_data );
// 如果要修改:void get_data ( sturct student & student_data );
int main(){
student student1;
void get_data( student1 );
···
}
输出:
结构体与数组不同,传入的是副本;如果想要修改,需要按引用传递(&)
但是,结构体数组的性质与数组一致;即:结构体数组可以直接修改,无需按引用传递;
另外要注意的一点是:
按值传递结构体的时间开销是较大的;因此,按引用传递是更加合理的;为防止实参在结构体内被修改,我们可使用const;
void get_data ( const sturct student & student_data );
字符串(c++ string):
正如结构体数组与数组类似,我们可以认为字符串与结构体相似,面临的问题与结构体相同;
而我们采取的解决方法也与结构体相同:
int count ( const string & str );
c-string :
c-string的本质就是数组(只是最后加了 ‘\0’ );
因此处理方法与数组相同;
...
int count ( const string & ch );
int main(){
char greeting[] = "hello world";
count ( greeting );
...
}
...
3.多态
静态多态:
发生在程序被编译时;
类型:
1.函数重载;
同一个程序重使用相同名字的不同函数
要求:形参不同(个数或类型)
int sum ( const int array[] , int num );
int sum ( const int array[][2] , int num );
int sum ( const int array[] , int num , float score );
int sum ( const int array[] , int num , int score );
程序根据实参与形参的匹配结构来确定调用哪个sum();
2.运算符重载;
定义一个新的类时,可重新定义或重载已存在的运算符;
...
class time_24{
public:
time_24 ( int h = 0, int m = 0, int s =0);
void set_time( int h , int m , int s );
void get_time( int& h , int& m , int & s );
time_24 operator+ ( int s ) const;
//重载+,形参是一个int型数据,返回一个time_24的对象;
//句末的const确保该函数的对象在函数中不会被修改;
//这个函数的函数名为 operator+(),调用方法与其他函数无异;
private:
int hours;
int minutes;
int seconds;
};
time24::time24 ( int h, int m, int s):
hours( h), minutes( m), seconds( s)
{ }
void set_time( int h , int m , int s ){...}
void get_time( int& h , int& m , int & s ){...}
time24 time24 : : operator+( int s ) const{
time24 temp;
temp.seconds = seconds +s;
temp.minutes = minutes + temp . seconds / 60 ;
temp. seconds %=60 ;
temp .hours = hours + temp.minutes / 60 ;
temp.minutes %=60 ;
temp. hours %=24 ;
return temp ; .
}
//重载后的+可以实现时间的加法;
int main(){
int h, m, s;
time24 t1( h, m, )
t2 = t1 + 4 ;
//这里使用的是重载后的+;
//其实等效于:
//t2=t1.operator+(4);
//error:
//t2=4+t1;
//t3=t1+t2
//这两钟情况需要定义;
...
}
注:
1.
. .* :: ?: sizeof 不可重载
// ?:是if-else的缩写;
//max = ( num1 > num2 ) ? num1 : num2 ;
2.不可发明新的运算符;
3.操作数个数不可变;如:+是2个,而++是一个;
4.优先级不变;
5.用于内置数据类型时(int、float .etc),不能重新定义;
3.模板;
生成类或函数的框架;
#ifndef _MAXIMUM_H //避免双重定义;
#defined MAXIMUM_H
#include "maximum.h"
template < typename T >
T maximum ( const T n1, const T n2 )
{}
#endif
注:
1.必须要加typename:template<typename n1,n2>;
2.每个指定类型形参都必须被使用:
template < typename T1,typename T2 >
int fun ( T1 var ) //error: T2 is not used;
3.引用类模板必须包含形参:
stack<T> i_stack
动态多态:
发生在程序运行时,直到程序运行时才知道调用哪个函数;
类型:
虚函数;
class circle{
public:
virtual double area( );
void area_message ( ){
cout << message << area() << endl; //注意area();
}
...
};
class cylinder : public circle{
...
virtual double area( );
...
}
class...
int main()
{
circle* ptr; //指向基类的指针;
...
if...{
ptr = new circle ( radius ); //指向派生类
}
if...{
ptr = new cylinder ( radius , height ); //指向派生类
}
ptr -> area_message( ); //调用基类中area_message( )
...
注:
1.定义为指向基类的指针是特殊的,可指向任何派生类;
2.如果一个基类中成员函数可能被覆盖,就将其声明为虚函数;
纯虚函数:
//基类;
class student{
...
virtual void disp_details ( ) = 0 ;
//该函数内没有代码,且被复制为0;
//
...
}
class boy :student {
...
virtual void disp_details ( ) ;
...
}
int main ()
{
student * ptr ;
if...{
ptr = new boy;
}
ptr -> disp_details ( )
//如果没有纯虚函数,则报错;
//因为基类( student() )中必须要有disp_details ( ) ;
}
有纯虚函数的基类,称为抽象基类;
4.其他
this指针
指向调用成员函数的对象;
... //定义time24;
//重载++;
time24 time24::operator++(){
*this = *this + 1;
return *this;
}
main()
{
...
++t1; //this指向t1;
...
}
友员函数
可读取private的非成员函数;
class Student{
private:
double score;
public:
friend operate ( Student person );
void sum ( double score );
};
//声明
void Student::sum ( double score ){
...
}
void sum ( Student person ){
cout << person.score << endl;
}
//可访问person中任何成员;
注:
1.opreate不是任何类的成员函数;
2.可访问所有的成员
初始化
初始化类的时候会自动调用函数
class student{
public:
student( int h, float s ){
hours=h ; score=s ;
}
//或则
/*student( int h, float s ):
hours( h ) ,score( s )
{ } */
}
...
private:
int hours;
float score;
}
在继承中:
class Point {
protected:
double X,Y;
public:
point ( double x, double y ) :
X ( x ), Y ( y )
{ }
...
}
class Circle:public Point{
protected:
double radius;
public:
Circle ( double x=0, double y=0, double r=0 ) :
Point(x,y) {
X=x;Y=y;radius=r;
}
}
class Cone:Circle{
protected:
double height;
public:
Cone ( double x=0, double y=0, double r=0, double h=0 ):
Circle(x,y,r){
height=h;
}
}
...
析构函数
自带析构函数,但有时不够用;
一student般会加~;
class student{
private:
char* p;
public:
student ( int n ) ;
~student () ;
};
student::~student(){
delete[] p; //释放内存;
}
student::String(int n){
p = new char[n];
}
调用顺序是先初始化函数,再成员函数。再析构函数;
5.其他函数
1.compare()
比较字符串
#include<string>
...
Position="empolyee"
if ( Position.compare("Boss")==0 )
...
2.get() / put()
输入/输出单个字符
char char_in;
cin.get();
char char_out;
cout.put(char_out)
3.getline()
getline ( cin, in_name );
ignore ( 80, ' \n ');