类
类似于C语言中的结构,在C语言中可以定义结构,但这种结构中包含数据,而不包含函数。C++中的类是数据和函数的封装体。在C++中,结构可作为一种特殊的类,它虽然可以包含函数,但是它没有私有或受保护的成员。私有
、公有
和受保护成员
,C++类中可定义三种不同访控制权限的成员。一种是私有(Private)成员,只有在类中说明的函数才能访问该类的私有成员,而在该类外的函数不可以访问私有成员;另一种是公有(Public)成员,类外面也可访问公有成员,成为该类的接口;还有一种是保护 (Protected)成员,这种成员只有该类的派生类可以访问,其余的在这个类外不能访问。 using std::cout;
using std::endl; 或 using namepace std;
using std::cin;
namespace name_3
{
namespace
{
int k = 200;
};
};
namespace name = name_3;
例程中声明一个命名空间Test,Test中声明一个结构体Account,而Account中定义变量和声明函数。
namespace Test
{
struct Account
{
char name[30];
double balance;
void init(char *myname,double mybalance)
{
strcpy(name,myname);
balance = mybalance;
}
void deposit(double amount);
void withdraw(double amount);
inline double getBalance()
{
return balance;
}
};
}
常量折叠
。 c++中 编译器不会为一般的const常量分配内存空间, 而是将它们存放符号表中。如果取了这个常量的地址,那么编译器将为此常量分配一个内存空间,生成一个常量副本, 所有通过地址对常量的操作都是针对副本。 常量折叠,又叫常量替换,c++编译器会在编译时,将const常量的字面值保存在符号表中,在编译时使用这个字面常量进行替换。const_cast用法:const_cast<type_id> (expression) 该运算符用来修改类型的const或volatile属性。除了const或volatile修饰之外,要求type_id和expression的类型是一样的。 常量指针被转化成非常量的指针,并且仍然指向原来的对象; 常量引用被转换成非常量的引用,并且仍然指向原来的对象;
#include <iostream>
using namespace std;
int main(int argc, const char** argv)
{
const int a = 10;
const int *p = &a;
// (*p) = 11; // error 不可修改
std::cout << "a:" << a << "*p:" << *p << std::endl; // a:10 *p:10
const_cast<int&>(*p) = 11; // 强制修改
std::cout << "a:" << a << "*p:" << *p << std::endl; // a:10 *p:11
return 0;
}
#include <iostream>
using namespace std;
int main(void)
{
int a = 10;
// int &ref; // error! 必须初始化
// int &ref = 10; // error!
// const int &ref = 10; // ok
const int &ref_a = a; // ok
// ref_a = 11;
a = 12;
cout <<"ref_a: "<<a<< endl;
/* const int b = 20;
int &ref_b = b; // error! 非const引用不能绑定到const变量
const int &res_b = b; // ok
int c = 11;
const int &ref_c = c; // ok
//ref_c++; // error!
*/
return 0;
}
#include <iostream>
using namespace std;
#define max(a,b) (a>b?a:b)
int max1(int a,int b)
{
return a>b?a:b;
}
inline int max2(int a,int b)
{
return a>b?a:b;
}
int main(void)
{
cout <<"#define: "<<max(11,12)<<endl; //预处理阶段替换
cout <<"max1: "<<max1(12,11)<<endl; //函数的压栈出栈
cout <<"max2: "<<max2(12,11)<<endl; //运行时内联的展开
return 0;
}
#include <iostream>
using namespace std;
/*
*默认参数:如果某个参数被默认初始化了,其右边不能出现没有被默认初始化的参数
* Error:
* int average(double a=0.5, double b =1.1, double c)
* {
* return (a+b+c)/2;
* }
*/
int average(double a=0.5, double b =1.1, double c=2.1)
{
return (a+b+c)/2;
}
int average(int a, int b)
{
cout <<"average(int, int)" << endl;
return (a+b)/2;
}
int average(double a, double b)
{
cout <<"average(double, double)" << endl;
return (a+b)/2;
}
int average(double a, double b, double c)
{
cout <<"average(double,double,double)" << endl;
return (a+b+c)/2;
}
int main(void)
{
int a = 10, b = 11;
average(a, b);
cout <<"--------------" << endl;
double c = 10.1, d = 10.2, e = 10.3;
average(c, d);
cout <<"--------------" << endl;
average(c, d, e);
return 0;
}
#include <iostream>
using namespace std;
class Person{
public:
Person(){}
~Person(){}
void set(int var)
{
this->m_var = var;
}
int get() const //常成员函数
{
// m_var2 = 12; //error! 不修改成员变量
return m_var;
}
private:
int m_var;
int m_var2;
};
int main(void)
{
const Person p; // 常对象
//p.set(11); // error! const对象不能修改非const成员函数
const_cast<Person &>(p).set(11); //ok 只对当前生效
cout <<"const_cast: "<< p.get() <<endl;
//p.set(12); //error! 同样是不对的
return 0;
}
#include <iostream>
using namespace std;
class Person{
public:
Person(){
cout <<"constructor" << endl;
m_counter++;
}
~Person(){
cout <<"distructor" << endl;
m_counter--;
}
static void out_counter(){
//cout <<m_var<< endl; // error 不能访问普通成员变量
cout <<"people counter: "<<m_counter << endl; //ok
}
// private:
int m_var;
static int m_counter;
};
int Person::m_counter = 0; // 静态成员变量初始化
int main(void)
{
Person p1; //constructor
Person p2; //constructor
Person p3; //constructor
// p1.out_counter();
// p3.out_counter();
Person *p4 = new Person; //constructor
cout <<"people counter: "<<Person::m_counter << endl; // people counter:4
delete p4; //distructor
cout <<"people counter: "<<Person::m_counter << endl; // people counter:3
return 0;
}
person.h
namespace mystd
{
class Person
{
private:
char name[30];
int age;
bool gender;
public:
Person(char *myname, int age, bool gender);
~Person();
void show(); // 显示基本属性信息
int afterYear(int n); // n年后多少岁
inline int getAge()
{
return age;
}
};
};
person.cpp
#include "person.h"
#include <iostream>
#include <string.h>
using namespace std;
namespace mystd
{
Person::Person(char *myname, int myage, bool mygender)
{
strcpy(name, myname);
age = myage;
gender = mygender;
}
Person::~Person(){}
void Person::show() // 显示基本属性信息
{
cout <<"name: "<<name<<" age: "<<age<<" gender: "<<gender << endl;
}
int Person::afterYear(int n)// n年后多少岁
{
return age += n;
}
};
main.cpp
#include "person.h"
#include <iostream>
using namespace std;
using namespace mystd;
int main(void)
{
Person p1("Lin", 24, true);
p1.show();
cout <<"after ten years: " << p1.afterYear(10)<<endl;
cout <<p1.age<< endl;
return 0;
}
constructor.cpp
#include <iostream>
using namespace std;
class Person
{
public:
Person(){cout <<"---constructor---"<< endl;}
// Person(int a){m_var1 = a;}
Person(int a):m_var1(a),m_var2(m_var2),m_var3(a)
{
// m_var3 = 3; //error
cout <<"Person(int, int) constructor" << endl;
}
~Person(){cout <<"---distructor---" << endl;}
void show(){cout <<"m_var1: "<<m_var1 <<" m_var2: "<<m_var2<< endl;}
private:
int m_var1;
int m_var2;
const int m_var3;
// int &ref;
};
Person p1(10);
int main()
{
// Person p(10, 30);
// p.show();
cout <<"----------------" << endl;
Person *p = new Person(10);
p->show();
delete p;
p1.show();
cout <<"----------------" << endl;
return 0;
}
copy_constructor.cpp
#include <iostream>
#include <string>
using namespace std;
class Computer{
public:
Computer(){}
Computer(Computer&){
cout <<"----computer constructor----" << endl;
}
~Computer(){}
private:
string name;
};
class Student{
public:
Student(){}
Student(string name, int age){
cout <<"----constructor----" << endl;
Computer com;
m_comp = com;
this->name = name;
this->age = age;
}
//拷贝构造函数
Student(const Student &s){
cout <<"----copy constructor----" << endl;
this->name = s.name;
this->age = s.age;
}
~Student(){}
//把一个对象作为返回值的时候会调用该对象的一个拷贝构造函数
Computer getComp(){
cout <<"getComp()"<< endl;
return m_comp;
}
Student getst(){
return *this; //会调用该对象的拷贝构造函数
}
void disp(){
cout <<"name: "<<name<<" age: "<<age << endl;
}
private:
string name;
int age;
Computer m_comp;
};
//把对象作为参数进行值传递的时候拷贝构造函数会被调用
void disp_out(Student s)
{
s.disp();
}
int main(void)
{
Student s1("Lin", 20);
s1.disp();
Student s2 = s1; // 自动调用拷贝构造函数
s2.disp();
Student s3(s2); // 显式使用拷贝构造函数
s3.disp();
cout <<"******************" << endl;
disp_out(s3); // 把一个对象作为值传递的时候会调用拷贝构造函数
cout <<"------------------" << endl;
s1.getComp();
s3.getst();
return 0;
}
deep_copy.cpp
#include <iostream>
#include <string.h>
using namespace std;
class Mystring{
public:
Mystring(char *str, int counter){
m_str = new char[counter+1];
memcpy(m_str, str, counter);
m_counter = counter;
m_str[counter+1] = '\0';
}
//显示定义拷贝构造函数 进行深拷贝(也就是进行内存的拷贝)
Mystring(const Mystring &str){
// m_str = str.m_str; // error!
cout <<"deep copy constructor" << endl;
this->m_str = new char[str.m_counter+1];
memcpy(m_str, str.m_str, str.m_counter);
this->m_counter = str.m_counter;
m_str[m_counter+1] = '\0';
}
~Mystring(){
cout <<"distructor" << endl;
delete []m_str;
}
void disp(){
cout <<hex<<m_str<< endl;
}
private:
char *m_str;
int m_counter;
};
int main(void)
{
Mystring str("briupemsd1109", 13);
str.disp();
Mystring str1 = str; //用一个已有的对象去构造一个新的对象
str1.disp();
return 0;
}
address.h
#ifndef _ADDRESS_H_
#define _ADDRESS_H_
#include <string>
#include <iostream>
using namespace std;
class Address{
public:
Address(){}
Address(string country, string province, string city, string street)
{
this->country = country;
this->province = province;
this->city = city;
this->street = street;
}
~Address(){}
void setProvince(string province){
this->province = province;
}
string getProvince() const{
return province;
}
void setStreet(string street){
this->street = street;
}
string getStreet() const{
return street;
}
void out(){
cout <<country<<"-"<<province<<"-"<<city<<"-"<<street<<endl;
}
private:
string country;
string province;
string city;
string street;
};
#endif
player.h
#ifndef _PLAYER_H_
#define _PLAYER_H_
#include "address.h"
#include <iostream>
using namespace std;
class Player{
public:
Player(){addr = NULL;}
Player(int num, string name, int age, double salary)
{
this->num = num;
this->name = name;
this->age = age;
this->salary = salary;
this->addr = NULL;
}
Player(int num, string name, int age, double salary, Address *addr){
this->num = num;
this->name = name;
this->age = age;
this->salary = salary;
this->addr = addr;
}
~Player(){}
void setNum(int num){
this->num = num;
}
int getNum() const{
return num;
}
void setAge(int age){
this->age = age;
}
int getAge() const{
return age;
}
void setSalary(double salary){
this->salary = salary;
}
double getSalary() const{
return salary;
}
void setAddress(Address *addr){
this->addr = addr;
}
Address *getAddress(){
return addr;
}
void out(){
cout <<"num: "<<num<< endl;
cout <<"name: "<<name<< endl;
cout <<"age: " <<age<<endl;
cout <<"salary: "<<salary <<endl;
if(addr != NULL){
addr->out();
}
cout <<"******************" << endl;
}
private:
int num;
string name;
int age;
double salary;
Address *addr;
};
#endif
player_test.cpp
#include "address.h"
#include "player.h"
#include <iostream>
using namespace std;
int main(void)
{
Address addr("china", "shanghai", "shanghai","huaihai RD");
Player p1(17, "Lin", 24, 10000, &addr);
p1.out();
cout <<"-------------------" << endl;
Player p2(24, "Kobe", 34, 20000);
Address addr2("china", "jiangsu", "kunshan","xuey RD");
p2.setAddress(&addr2);
p2.out();
cout <<"-------------------" << endl;
Address *addr3 = new Address("USA", "MAIAMI", "MAIAMI", "MM.RD");
Player *p3 = new Player(6, "James", 28, 20000, addr3);
p3->out();
delete addr3;
delete p3;
return 0;
}
类具备封装和信息隐藏的特性。只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的。非成员函数能够访问类中的公有成员,但是假如将数据成员都定义为公有的,这又破坏了隐藏的特性。另外,应该看到在某些情况下,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间开销,而影响程序的运行效率。 为了解决上述问题,提出一种使用友元的方案。友元是一种定义在类外部的普通函数,但他需要在类体内进行说明,为了和该类的成员函数加以区别,在说明时前面加以关键字friend。友元不是成员函数,但是他能够访问类中的私有成员。友元的作用在于提高程序的运行效率,但是,他破坏了类的封装性和隐藏性,使得非成员函数能够访问类的私有成员。
友元函数
: 友元函数的特点是能够访问类中的私有成员的非成员函数。友元函数从语法上看,他和普通函数相同,即在定义上和调用上和普通函数相同。友元类
: 友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。 当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。定义友元类的语句格式如下: friend class 类名; 其中:friend和class是关键字,类名必须是程序中的一个已定义过的类。 例如,以下语句说明类B是类A的友元类: class A { … public: friend class B; … }; 经过以上说明后,类B的所有成员函数都是类A的友元函数,能存取类A的私有成员和保护成员。注意事项: 1.友元可以访问类的私有成员。 2.只能出现在类定义内部,友元声明可以在类中的任何地方,一般放在类定义的开始或结尾。 3.友元可以是普通的非成员函数,或前面定义的其他类的成员函数,或整个类。 4.类必须将重载函数集中每一个希望设为友元的函数都声明为友元。 5.友元关系不能继承,基类的友元对派生类的成员没有特殊的访问权限。如果基类被授予友元关系,则只有基类具有特殊的访问权限。该基类的派生类不能访问授予友元关系的类。
继承
:类与类之间的关系 父类(基类) 子类(派生类) 继承语法 构建子类对象,先调用父类的构造函数,再调用子类自己的构造函数,析构的时候先调用子类自己的析构函数,再调用父类的析构函数 父类中的public和protected的成员变量和成员函数都会被子类继承下来
覆盖
: 如果子类中有和父类函数名相同且参数相同的成员函数,则在子类对象调用该成员函数时会把父类的覆盖掉
隐藏
: 如果子类中有和父类函数名相同但参数不同的成员函数, 则会在父类中该名称的成员函数会被隐藏掉
父类的指针绑定子类的对象 OK 子类的指针绑定父类的对象 error!
通过对象指针进行的普通成员函数调用,仅仅与指针的类型有关,而与此刻指针正指向什么对象无关。想要实现当指针指向不同对象时执行不同的操作就必须将基类中相应的成员函数定义为虚函数。
inherit.cpp
#include <stdio.h>
#include <iostream>
using namespace std;
// 派生类是基类的具体化,而基类是派生类的抽象。
// 在多继承时,如果省略继承方式,默认为private
// 如果在派生类中声明了一个与基类成员相同名字的函数,派生类的新成员会覆盖基类的同名成员
/* 不管何种继承 基类的私有程序都不能被派生类继承 否则会破坏C++的封装特性
* 基类的友元函数也不能被继承,友元只是能访问指定类的私有和保护成员的自定义函数,不是被指定类的成员,自然不能继承
* 基类与派生类的静态成员函数与静态成员是共用一段空间的,即静态成员和静态成员函数是可以继承的
*/
// public公有继承时 基类的公用成员public和保护成员protected在派生类中保持原有的访问属性,其私有成员仍为基类私有,即在派生类中不能访问,在类外也不能访问
// protected保护继承 特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元访问,基类的私有成员仍然是私有的
// private私有继承 私有继承即所有基类成员均变成派生类的私有成员,基类的私有成员仍然不能在派生类中访问
class BASE
{
public:
void who()
{
cout << "this is base !" << endl;
}
void Fun()
{
cout << "this is base Fun ! " << endl;
}
};
class CD1:public BASE
{
public:
void who()
{
cout << "this is CD1 !" << endl;
}
};
class CD2:public BASE
{
public:
void who()
{
cout << "this is CD2 !" << endl;
}
};
int main(int argc, char* argv[])
{
CD1 obj1;
CD2 obj2;
obj1.Fun();
obj2.Fun();
obj1.who(); //this is CD1 !
obj2.who(); //this is CD2 !
return 0;
}
在函数形参表后面写上= 0以指定纯虚函数,含有纯虚函数的对象(抽象类)不能被实例化,只能作为基类被继承。
virtual.cpp
#include <stdio.h>
#include <iostream>
using namespace std;
/**************************
*加virtual与不加virtual的区别
***************************/
class BASE
{
public:
void who()
{
cout << "this is base !" << endl;
}
/*
virtual void who() //virtual
{
cout << "this is base !" << endl;
}
*/
};
class CD1:public BASE
{
public:
void who()
{
cout << "this is CD1 !" << endl;
}
};
class CD2:public BASE
{
public:
void who()
{
cout << "this is CD2 !" << endl;
}
};
int main(int argc, char* argv[])
{
BASE obj;
BASE *p;
CD1 obj1;
CD2 obj2;
p = &obj;
p->who();
p = &obj1;
p->who();
p = &obj2;
p->who();
obj1.who();
obj2.who();
return 0;
}
C++中的一个概念:泛型编程
:所谓泛型编程就是独立于任何特定类型的方式编写代码。模板是泛型编程的基础。
template <typename T> inline T min(const T&, const T&); //ok
inline template <typename T> T min(const T&, const T&); //error
C++
获取全部实例代码。#include <iostream>
using namespace std;
class A{
public:
A():m_var1(10),m_var2('a'),m_var3('b'){}
~A(){}
void disp(){
cout <<"m_var1="<<m_var1<<" m_var2="<<m_var2<<" m_var3="<<m_var3<<endl;
}
private:
int m_var1;
char m_var2;
char m_var3;
};
int main(void)
{
A a;
a.disp();
cout <<"m_var1: "<<*((int*)(&a))<< endl;
cout <<"m_var2: "<<*((char*)(&a)+4)<<endl;
cout <<"m_var3: "<<*((char*)(&a)+5)<<endl;
cout <<sizeof(a) << endl;
/*
m_var1=10 m_var2=a m_var3=b
m_var1: 10
m_var2: a
m_var3: b
8
*/
return 0;
}