[c++语法]类
什么是类
类 是 面向对象的基础。c里面是没有对象的,只有数据,即静态的死物。
从面向过程升级到面向对象后,有了对象的概念,对象是数据与方法的合体,是动态的活物。
类代表着一类事物的特征。而对象,是类的具体化,实例化。
类的声明与定义
一般来说,类的声明在相应的头文件中,类的定义在相应的源文件中。这样实现了接口与实现的分离。
//Dog.h #ifndef _DOG_H_
#define _DOG_H_ #include <string>
#include <iostream> class Dog { //类的声明
public: //公共成员
Dog(){} //默认构造函数
Dog(float weight) : weight(weight){ //可以隐式转换
sex = true;
}
explicit Dog(bool isMale) : sex(isMale){} //explicit 修饰不可以隐式转换
Dog(float weight , bool sex); Dog(const Dog &dog) : weight(dog.weight) , sex(dog.sex) , name(dog.name) , power(dog.power){}; //复制构造函数
Dog& operator=(const Dog &dog){ //赋值函数
weight = dog.weight;
sex = dog.sex;
} ~Dog(){ //析构函数 } void bellow();
inline std::string toString(); // 类定义外部的inline方法,方法定义必须与类定义在同一个文件
float getWeight() const{ //类定义内部定义的方法,默认为inline
return weight;
} void info(std::ostream& out); static int getNum() { //静态成员函数
return num;
} // int t1 = 1; //error , 类定义中成员变量不能初始化。
const static int t2 = 3; //只有 const static 类型才能在类定义中初始化。
static int t3; //static 成员变量初始化写在源文件中。
protected: //保护成员 private: //私有成员
float weight;
bool sex;
mutable int power; //mutable类型变量,在const 对象中依然可以修改。
std::string name;
static int num; // 静态成员变量 }; std::string Dog::toString(){ // 类定义外部的inline方法,方法定义必须与类定义在同一个文件
std::string str("Dog[name=");
str+=name;
str+=",weight=";
str+=weight;
str+=",sex=";
str+=sex;
str+="]";
return str;
} #endif
//Dog.cpp #include "Dog.h"
#include <iostream> void Dog::bellow(){ //类方法的定义
std::cout<<"wang wang wang"<<std::endl;
} void Dog::info(std::ostream& out){
out << "Dog[name=" << name <<",weight=" << weight <<",sex=" << sex <<"]" << std::endl;
} //const int Dog::t2; //const static 成员定义。
int Dog::t3 = 10; //static 成员初始化。
类的实例化
Dog d(1.0f);
Dog *d2 = new Dog(1.0f);
类的初始化:构造函数
当创建一个类对象时,构造函数将会被调用。
如:
语句 Dog d(1.0f);
Dog *d2 = new Dog(1.0f);
会使编译器调用 Dog(float w) : weight(w) {} 来初始化对象
构造函数分为3部分:函数签名(函数名加形参列表),即 Dog(float w)
初始化列表 冒号与大括号之间的部分为初始化列表。即 weight(w)
构造函数 即大括号中的内容。
构造函数执行时,先执行初始化列表,然后再执行构造函数。
先执行初始化列表:
初始化列表的任务是 初始化类中的成员变量。顺序是按照类中声明的顺序挨个初始化。
类类型成员初一定初始化,在初始化列表的,就用初始化列表中的初始化方法。不在初始化列表的,就调用类的默认构造函数。 从这里可以看出,没有默认构造函数的类类型,引用类型,const类型 必须在初始化列表。
内置类型和复合类型的不一定初始化,如果在初始化列表,就用初始化列表中的初始化方法。如果不在,就得看对象的位置,全局的初始化,局部的不初始化。
然后再执行构造函数
//playdog.cpp #include <iostream>
#include <cstdlib>
#include "Dog.h" Dog gloabDog; int main(){
Dog localDog;
gloabDog.info(std::cout);
localDog.info(std::cout); return EXIT_SUCCESS;
}
输出:
由此,可以看出对象是局部变量的情况下,没有出现在相应初始化列表的内置类型类成员没有初始化。
复制构造函数与赋值函数
复制构造函数是一个特殊的构造函数。它只有一个参数,相同类对象的引用。
赋值函数是将相同类的对象赋值给对象。
Dog(const Dog &dog) : weight(dog.weight) , sex(dog.sex) , name(dog.name) , power(dog.power){};   //复制构造函数
Dog& operator=(const Dog &dog){	                                                                 //赋值函数
        weight = dog.weight;
	sex = dog.sex;
}
Dog d1;
Dog d2(d1); //调用复制构造函数
Dog d3 = d1; //调用复制构造函数
Dog d4;
d4 = d1; //调用赋值函数
赋值构造函数,赋值函数,如果不写的话,编译器会默认一个。系统默认的 就是将成员变量按照声明的顺序挨个复制一遍。
复制构造函数出现的地方:
1,上面的显示调用。
2,对象作为方法参数传入, 对象作为方法返回值返回。
3,初始化容器
4,初始化数组元素
Dog d2(d1);		//显示调用
std::string caculate(std::string str1 , std::string str2);	//形参,返回值
std::vector<std::string> svec(5);	//先调用string的默认构造函数生成一个string临时对象,然后调用5次复制构造函数来初始化容器
std::string[] strs = {				//显示调用构造函数生成临时对象,然后调用复制构造函数来初始化数组元素
					string("hello"),
					string("word")
				}
析构函数
析构函数是删除对象时调用的方法,用来释放对象占用的资源。析构函数是无论是否编写,编译器都会默认一个析构函数。这个默认的析构函数就是按照成员变量声明的顺序的倒序挨个释放资源,如果是类类型,就调用该对象的析构函数。
调用析构函数的时候,先调用用户写的,然后再调用编译器默认的。
三法则
复制构造函数,赋值函数,析构函数, 这三个函数什么时候需要写呢?
一般来说,类中有指针成员变量,或者有需要特殊控制的资源,就需要写。这是3个函数一定是同时需要写,或同时不需要写。静态成员
类中static 修饰静态成员。静态成员属于类,不属于任何一个对象。
所以 static方法中不能使用 this,不能访问非静态方法,非静态变量。
静态成员变量在类定义时初始化。定义在类定义中,初始化在类方法实现源文件中。
c++ primer 中说 const static 成员在类定义中声明初始化,但是还必须在类实现源文件中在空初始化一次。
如: 类定义中 const static int t2 = 3; 但是还必须在Dog.cpp中 const int t2;
但在我的机器上,Dog.cpp中不加这一句仍然没问题。
static 成员的调用
int main(){
	std::cout << Dog::t3 << std::endl;
	std::cout << Dog::t2 << std::endl;
	return EXIT_SUCCESS;
}
类的封装
这里由类的成员访问限定符(member access specifier)实现。
public 任意都可访问。
private 只有本类可访问
protected 不能被类外访问(这点与私有成员类似),但可以被派生类的成员函数访问。
默认内联函数
c++中,inline表示内联函数。在程序调用这些成员函数时,并不是真正地执行函数的调用过程(如保留返回地址等处理),而是把函数代码嵌入程序的调用点。这样可以大大减少调用成员函数的时间开销。
C++要求对一般的内联函数要用关键字inline声明,但对类内定义的成员函数,可以省略inline,因为这些类内定义成员函数已被隐含地指定为内联函数。
如 float getWeight() const 就默认为内联函数了。
不在类定义内定义的内联函数,必须在类定义同一个文件中定义。
如 inline std::string toString(); 必须也在Dog.h 中定义,如果在Dog.cpp中定义,就会出现编译错误。
构造函数隐式转换
只有一个形参的构造函数可以参与隐式转换。
如 因为有构造函数 Dog(float weight)
Dog d = 1.0f;
编译器会把 float 类型 的 1.0f 通过 Dog(float weight) 隐式转换成一个临时的 Dog 类型对象,然后赋值给d.
explicit 修饰构造函数 可以禁止 隐式转换。
[c++语法]类的更多相关文章
- oc 基本语法 类 静态变量 常量
		
// // ReViewClass.h // hellowWorld // 本类是oc复习练手类 // Created by hongtao on 2018/3/26. // Copyright © ...
 - ES6深入浅出-8 新版的类(下集)-1.简单语法
		
回顾 当你声明一个空的对象obj的时候,会生成一块内存这个内存里面什么都没有,自由__proto__存在401的地址. 也就是Object的protototype在内存中的地址 类 通过函数创建类.这 ...
 - swift学习笔记3——类、结构体、枚举
		
之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...
 - IOS基础之 (三) 类的声明和对象的创建
		
一 OC类的声明和实现语法 1.接口的声明 @interface NewClassName: ParentClassName { 实例变量 ... } 方法的声明 ... @end //...表示省略 ...
 - Ruby学习: 类的定义和实例变量
		
ruby是完全面向对象的,所有的数据都是对象,没有独立在类外的方法,所有的方法都在类中定义的. 一.类的定义语法 类的定义以 class 关键字开头,后面跟类名,以 end标识符结尾. 类中的方法以 ...
 - Swift 的类、结构体、枚举等的构造过程Initialization(下)
		
类的继承和构造过程 类里面的全部存储型属性--包含全部继承自父类的属性--都必须在构造过程中设置初始值. Swift 提供了两种类型的类构造器来确保全部类实例中存储型属性都能获得初始值,它们各自是指定 ...
 - C++_进阶之函数模板_类模板
		
C++_进阶之函数模板_类模板 第一部分 前言 c++提供了函数模板(function template.)所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来 ...
 - swift 学习- 10 -- 类和结构体
		
// '类和结构体' 是人们构建代码所使用的一种通用且灵活的构造体, 我们可以使用完全相同的语法规则来为 '类和结构体' 定义属性 (变量 和 常量) 和添加方法, 从而扩展 类和结构体 的功能 // ...
 - java基础语法2.
		
第二章 2.1 class文件的生成 java文件为源代码文件 class为程序. class文件实时修改. eclipse自动生成. project下面clean. 2.2 jar文件 如何将有用的 ...
 
随机推荐
- Python与开源GIS:在OGR中使用SQL语句进行查询
			
摘要: 属性选择与空间选择都可以看作是OGR内置的选择功能,这两种功能可以解决大部分实际中的问题.但是也有这种时候,就是进行查询时的条件比较复杂.针对这种情况,OGR也提供了更加灵活的解决方案:支持使 ...
 - 动态链接库dll的 静态加载 与 动态加载
			
dll 两种链接方式 : 动态链接和静态链接(链接亦称加载) 动态链接是指在生成可执行文件时不将所有程序用到的函数链接到一个文件,因为有许多函数在操作系统带的dll文件中,当程序运行时直接从操作系统 ...
 - 130825组队赛-Regionals 2012, North America - East Central NA
			
A.Babs' Box Boutique 一道简单的dfs搜索题,需要两两比较,然后搜到底,得到最大值就行了.比赛时队友写的,我只负责debug..赛后自己写的.. #include<iostr ...
 - C# - InnerList
			
运行效果: 代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; name ...
 - 技术不牛如何才拿到国内IT巨头的Offer(转)
			
不久前,byvoid面阿里星计划的面试结果截图泄漏,引起无数IT屌丝的羡慕敬仰.看看这些牛人,NOI金牌,开源社区名人,三年级开始写Basic...在跪拜之余我们不禁要想,和这些牛人比,作为绝大部分技 ...
 - SOLR搭建企业搜索平台
			
一. SOLR搭建企业搜索平台 运行环境: 运行容器:Tomcat6.0.20 Solr版本:apache-solr-1.4.0 分词器:mmseg4j-1.6.2 词库:sogou-dic ...
 - AngularJS_百度百科
			
AngularJS_百度百科 AngularJS 编辑 AngularJS是为克服HTML在构建应用上的不足而设计的. 目录 1简介引引 端对 ...
 - svn 标示提示
			
原来没有遇到过, 突然发现这次写的项目有几个文件时 这个"表示的" ,死活找不到原因,并且提交,改动 都好烦人,还要锁定什么嘛的. 最后最终知道, 这个意思是 文件的状态为 &q ...
 - 立波 iphone3gs越狱教程:成功把iphone3gs手机升级成ios6.1.3系统,完美越狱,解决no service和耗电量大的问题
			
前几天,老婆使用的iphone3gs摔地了,把手机里的连接电源的那个神马线给搞坏了,结果花了200多块大洋修好了: 修好后,老婆抱怨道:5年了,这手机好多软件都装不上,说手机版本号太低了, 我就说凑合 ...
 - sql: sql developer使用
			
在sql developer中登陆某数据库,在procedure里面加入一个proc,种类选ARBOR: CREATE OR REPLACE PROCEDURE PROCEDURE23 IS NAM ...