第01节:不可变对象、不可变类;避免多次声明
Date1.h
class Date
{
public:
Date(int newYear, int newMonth, int newDay);
//Date(int , int , int );
int getYear();
void setYear(int newYear);
private:
int year;
int month;
int day;
};
Date1.cpp
#include "Date1.h"
Date::Date(int newYear, int newMonth, int newDay)
{
year = newYear;
month = newMonth;
day = newDay;
}
int Date::getYear()
{
return year;
}
void Date::setYear(int newYear)
{
year = newYear;
}
Person1.h
#include "Date1.h"
class Person
{
public:
Person(int id, int year, int month, int day);
Person(Person &);//拷贝构造函数
int getId();
Date * getBirthDate();
private:
int id;
Date *birthDate;
};
Person1.cpp
#include "Person1.h"
Person::Person(int id, int year, int month, int day)
{
this -> id = id;
birthDate = new Date(year, month, day);
}
Person :: Person(Person &person)
{
id = Person.id;
Date *p = person.getBirthDate();
birthDate = new Date(*p);
}
int Person::getId()
{
return id;
}
Date * Person::getBirthDate()
{
return birthDate; // Return the pointer of the object
}
TestPerson1.cpp
#include <iostream>
#include "Person1.h"
#include "Date1.h" // Person1.h已经包含Date1.h 所以这里重复定义
using namespace std;
int main()
{
Person person(111223333, 1970, 5, 3);
Date *pDate = person.getBirthDate();
pDate -> setYear(2010);
cout << person.getBirthDate() -> getYear() << endl;
return 0;
}
解决方案1
#ifndef DATE1_H
#define DATE1_H
class Date
{
public:
Date(int newYear, int newMonth, int newDay);
//Date(int , int , int );
int getYear();
void setYear(int newYear);
private:
int year;
int month;
int day;
};
#endif
解决方案2
#pragma once
class Date
{
public:
Date(int newYear, int newMonth, int newDay);
//Date(int , int , int );
int getYear();
void setYear(int newYear);
private:
int year;
int month;
int day;
};
U05S01 - 不可变对象与Thread-safe
什么是 thread-safe?
不可变对象一定是 thread-safe 的吗?为什么?
答:1、Thread-safe:在多线程环境下,多个线程在访问共享数据时,为了保证该数据的安全而做出的一种承诺或者机制;
2、不可变对象本身有两层含义,一个是共享的数据(如果有)是只读的,另一个是与生俱来的线程安全性。可以说不可变对象是天生Thread-safe;(by m15522962525)
第02节:实例成员与静态成员
static 关键字将sq 限定在fun中,main函数无法调用
静态变量在静态区 所有共有而实例变量在栈区
Circle5.h
#ifndef CIRCLE_H
#define CIRCLE_H
class Circle
{
public:
Circle();
Circle(double);
double getArea();
double getRadius();
void setRadius(double);
static int getNumberOfObjects(); //static function
private:
double radius;
static int numberOfObjects; //static variable
};
#endif
Circle5.cpp
#include "Circle5.h"
// What will happen when commenting out the next line?
int Circle::numberOfObjects = 0;//静态变量只能在所有函数之外初始化
// Construct a circle object
Circle::Circle()
{
radius = 1;
numberOfObjects++;
}
// Construct a circle object
Circle::Circle(double radius)
{
this->radius = radius;
numberOfObjects++;
}
// Return the area of this circle
double Circle::getArea()
{
return radius * radius * 3.14159;
}
// Return the radius of this circle
double Circle::getRadius()
{
return radius;
}
// Set a new radius
void Circle::setRadius(double radius)
{
this->radius = (radius >= 0) ? radius : 0;
}
// Return the number of circle objects
int Circle::getNumberOfObjects()
{
return numberOfObjects;
}
好的编程风格:在静态变量前加入类名+域分隔符
第03节:析构函数与友元
缺点:打破了封装性
友元函数:TestFriendFunction.cpp
#include <iostream>
using namespace std;
class Date
{
friend void p();
private:
int year;
int month;
int day;
};
void p()
{
Date date;
date.year = 2000;
cout << date.year;
}
int main()
{
p();
return 0;
}
友元类:
Date2.h
class Date
{
public:
friend class AccessDate;
private:
int year;
int month;
int day;
};
TestFriendClass.cpp
#include <iostream>
#include "Date2.h"
using namespace std;
class AccessDate
{
public:
static void p()
{
Date birthDate;
birthDate.year = 2000;
cout << birthDate.year;
}
};
int main()
{
AccessDate::p();
return 0;
}
U05S03 - 关于友元的一些问题
-
两个类可以互为友元类吗?如果你能举出例子就更好了
-
其它的面向对象编程语言中,有friend这种东西或者类似的东西吗?
-
一个类可以有友元,友元能够访问这个类中的私有/保护成员;那么,一个函数是否可以有友元,通过友元访问这个函数中的局部变量?
答:1、可以的,代码如下:
class A{
public:
friend class B;
};
class B{
public:
friend class A;
};
int main(){
return 0;
}
2、Java中没有这个概念;
3、函数的局部变量在进程没有运行到该函数时,其是不存在的。即便定义了友元,甚至是规定了访问方法,也是无济于事的。(by m15522962525)
U05S03 - 析构函数的问题
析构函数为啥不能有参数?
析构函数为啥不能有返回值?
假如析构函数可以有参数,也可以有返回值,会有什么后果? 大胆猜一猜,说说你的看法
答:析构用来释放内存的,如果有返回值,返回值要存放在哪里,参数的值要放在哪里?(by 小嘉学长)
第04节:拷贝构造函数
只有在定义时用=才调用拷贝构造函数
浅拷贝例子
Date.h
#ifndef DATE_H
#define DATE_H
class Date
{
public:
Date(int newYear, int newMonth, int newDay);
int getYear();
void setYear(int newYear);
private:
int year;
int month;
int day;
};
#endif
Date.cpp
#include "Date.h"
Date::Date(int newYear, int newMonth, int newDay)
{
year = newYear;
month = newMonth;
day = newDay;
}
int Date::getYear()
{
return year;
}
void Date::setYear(int newYear)
{
year = newYear;
}
Person.h
#pragma once
#include "Date.h"
class Person
{
public:
Person(int id, int year, int month, int day);
int getId();
Date* getBirthDate(); // Return the pointer of the object
private:
int id_;
Date* birthDate ; // The pointer of the object
};
Person.cpp
#include "Person.h"
Person::Person(int id, int year, int month, int day)
{
id_ = id;
birthDate = new Date(year, month, day);
}
int Person::getId()
{
return id_;
}
Date * Person::getBirthDate()
{
return birthDate; // Return the pointer of the object
}
ShallowCopyDemo.cpp
#include <iostream>
#include "Person.h"
using namespace std;
void displayPerson(Person &person1, Person &person2)
{
cout << "\tperson1 id: " << person1.getId() << endl;
cout << "\tperson1 birth year: " <<
person1.getBirthDate() -> getYear() << endl;
cout << "\tperson2 id: " << person2.getId() << endl;
cout << "\tperson2 birth year: " <<
person2.getBirthDate() -> getYear() << endl;
}
int main()
{
Person person1(111, 1970, 5, 3);
Person person2(222, 2000, 11, 8);
cout << "After creating person1 and person2" << endl;
displayPerson(person1, person2);
person1 = Person(person2); // Copy person2 to person1
cout << "\nAfter copying person2 to person1" << endl;
displayPerson(person1, person2);
person2.getBirthDate() -> setYear(1963);
cout << "\nAfter modifying person2's birthDate" << endl;
displayPerson(person1, person2);
cout << "\n" << (person1.getBirthDate() == person2.getBirthDate());
return 0;
}
深拷贝
Person1.h
#include "Date1.h"
class Person
{
public:
Person(int id, int year, int month, int day);
Person(Person &);
int getId();
Date * getBirthDate(); // Return the pointer of the object
private:
int id;
Date *birthDate; // The pointer of the object
};
Person1.cpp
#include "Person1.h"
Person::Person(int id, int year, int month, int day)
{
this -> id = id;
birthDate = new Date(year, month, day);
}
Person::Person(Person &person)
{
id = person.id;
Date *p = person.getBirthDate();
birthDate = new Date(*p);
}
int Person::getId()
{
return id;
}
Date * Person::getBirthDate()
{
return birthDate; // Return the pointer of the object
}
CustomCopyConstructor.cpp
#include <iostream>
#include "Person1.h"
using namespace std;
void displayPerson(Person &person1, Person &person2)
{
cout << "\tperson1 id: " << person1.getId() << endl;
cout << "\tperson1 birth year: " <<
person1.getBirthDate() -> getYear() << endl;
cout << "\tperson2 id: " << person2.getId() << endl;
cout << "\tperson2 birth year: " <<
person2.getBirthDate() -> getYear() << endl;
}
int main()
{
Person person1(111, 1970, 5, 3);
Person person2(person1);
cout << "After creating person1 and person2" << endl;
displayPerson(person1, person2);
person2.getBirthDate() -> setYear(1963);
cout << "\nAfter modifying person2's birthDate" << endl;
displayPerson(person1, person2);
cout << "\n\nperson1.birthDate == person2.birthDate: " << boolalpha <<
(person1.getBirthDate() == person2.getBirthDate()) << "\n\n";
Person person3(111, 1970, 5, 3);
Person person4 = person3;
cout << "person3.birthDate =" <<
reinterpret_cast<int> (person3.getBirthDate()) << endl;
cout << "person4.birthDate =" <<
reinterpret_cast<int> (person4.getBirthDate()) << endl;
return 0;
}
U05S04 - 深/浅拷贝的神话传说老师参与
想必你被这一节跳来跳去的代码跳晕了吧?请往下看,你会更晕
到底啥是深/浅拷贝呢? 有一本书它名叫天方夜谭,神奇又好看,叙述的是阿拉伯的故事,到处都在流传…
话说你与你的好基友/蜜友外出探险:
你的好基友/蜜友拣了一神灯。Ta擦擦神灯,一个魔鬼从神灯中冒出来可以实现Ta的两个愿望。Ta说:1. 我要一山洞的财宝;2. 我要打开山洞的钥匙。
你也拣了一个神灯,擦擦神灯,一个魔鬼从神灯中冒出来可以实现你的两个愿望。你说:浅拷贝! 然后魔鬼给了你一把钥匙,能打开你好基友的山洞。。。你还剩下一个愿望。。。但是。。。最后你和你的好基友/蜜友因为争抢财宝而同归于尽
你也拣了一个神灯,擦擦神灯,一个魔鬼从神灯中冒出来可以实现你的两个愿望。你说:深拷贝! 然后魔鬼给了你另外一个山洞的财宝,给了你打开这个山洞的钥匙。。。。。。。。最后你和好基友/蜜友幸福滴生活在一起
第05节:示例分析
Course,h
#ifndef COURSE_H
#define COURSE_H
#include <string>
using namespace std;
class Course
{
public:
Course(const string &name);
string getName();
void addStudent(const string &student);
string * getStudents();
int getNumberOfStudents();
private:
string name;
string students[100];
int numberOfStudents;
};
#endif
Course.cpp
#include <iostream>
#include <cstdlib>
#include "Course.h"
using namespace std;
Course::Course(const string &name)
{
numberOfStudents = 0;
this -> name = name;
}
string Course::getName()
{
return name;
}
void Course::addStudent(const string &student)
{
if (numberOfStudents >= 100)
{
cout << "The maximum size of array exceeded" << endl;
cout << "Program terminates now" << endl;
exit(0);
}
students[numberOfStudents] = student;
numberOfStudents++;
}
string * Course::getStudents()
{
return students;
}
int Course::getNumberOfStudents()
{
return numberOfStudents;
}
TestCourse.cpp
#include <iostream>
#include "Course.h"
using namespace std;
int main()
{
Course course1("Data Structures");
Course course2("Database Systems");
course1.addStudent("Peter Jones");
course1.addStudent("Brian Smith");
course1.addStudent("Anne Kennedy");
course2.addStudent("Peter Jones");
course2.addStudent("Steve Smith");
cout << "Number of students in course1: " <<
course1.getNumberOfStudents() << "\n";
string * students = course1.getStudents();
for (int i = 0; i < course1.getNumberOfStudents(); i++)
cout << students[i] << ", ";
cout << "\nNumber of students in course2: " <<
course2.getNumberOfStudents() << "\n";
students = course2.getStudents();
for (int i = 0; i < course2.getNumberOfStudents(); i++)
cout << students[i] << ", ";
return 0;
}
StackOfIntegers.h
#ifndef STACK_H
#define STACK_H
class StackOfIntegers
{
public:
StackOfIntegers();
bool empty();
int peek();
int push(int value);
int pop();
int getSize();
private:
int elements[100];
int size;
};
#endif
StackOfIntegers.cpp
#include "StackOfIntegers.h"
StackOfIntegers::StackOfIntegers()
{
size = 0;
}
bool StackOfIntegers::empty()
{
return (size == 0);
}
int StackOfIntegers::peek()
{
return elements[size - 1];
}
int StackOfIntegers::push(int value)
{
//return elements[size++] = value;
elements[size] = value;
size++;
return value;
}
int StackOfIntegers::pop()
{
// Following 3 lines is for debug usage
int t = elements[--size];
elements[size] = -1;
return t;
// return elements[--size];
}
int StackOfIntegers::getSize()
{
return size;
}
TestStackOfIntegers.cpp
#include <iostream>
#include "StackOfIntegers.h"
using namespace std;
int main()
{
StackOfIntegers stack;
for (int i = 0; i < 10; i++)
stack.push(i);
while (!stack.empty())
cout << stack.pop() << " ";
return 0;
}
第06节:vector 类
第07节:更多编码规范
73号:一般将关键字放在行首
74:一般大括号在后面而不是另起一行