第1节:类的概念
第2节:创建对象并访问对象成员
问题:构造函数为什么不能有返回值?
答: 其实是有返回值的,返回this
不过 如果返回值会引起歧义,举个例子:
有个类是这个样子的:
class Test{
public:
int i;
int Test():i(0) { return 1;}
};
如果允许上面的定义成立,则会在下面的调用过程中产生矛盾。
调用过程:
Test t = Test();
1、这个是很普通的表达式,计算过程是从右边往左进行;
2、先看Test(),它会去调用类定义中的int Test():i(0) { return 1; }函数,并且生产一个临时的对象,姑且称呼为temp对象,temp对象的内部数据成员“i”的值是0;
3、与此同时,Test()返回了int型数据1;
4、此时,对象t就犯了难,到底是用int型数据1来对我进行初始化,还是用临时对象temp来对我进行初始化呢?
所以造成了歧义
(by m15522962525 superwukon)
第3节:关于创建对象的更多细节
struct中,如果不指明成员的访问控制属性,则默认的访问控制属性是:public
class中,如果不指明成员的访问控制属性,则默认的访问控制属性是:private
第4节:将声明与实现分离
Circle.h
class Circle{
public:
double radius;
Circle();
Circle(double);
double getArea();
};
Circle.cpp
#include "Circle.h"
Circle::Circle() {
radius = 1;
}
Circle::Circle(double newRadius) {
radius = newRadius;
}
double Circle::getArea() {
return radius * radius * 3.14159;
}
TestCircleWithDeclaration.cpp
#include <iostream>
#include "Circle.h"
using namespace std;
int main() {
Circle circle1;
Circle circle2(5.0);
cout << "The area of the circle of radius " <<
circle1.radius << " is " << circle1.getArea() << endl;
cout << "The area of the circle of radius " <<
circle2.radius << " is " << circle2.getArea() << endl;
// Modify circle radius
circle2.radius = 100;
cout << "The area of the circle of radius " <<
circle2.radius << " is " << circle2.getArea() << endl;
return 0;
}
问题:U04S04-有没有办法判断函数是否被编译器内联?
答:用 attribute((always_inline))强制内联
attribute((noinline)) 强制不内联(by 黑猫VC 1064780263)
第5节:对象指针与动态对象
问题 1 :
Circle circles[5];
Circle* p = circles;
你有多少种方法,可以调用circles数组中第0号对象的getArea函数呢?
答:circles[0].getArea()
(*circles).getArea()
circles->getArea();
(&circles[0])->getArea();
p->getArea();
(p+0)->getArea();
*p.getArea();
(&p[0])->getArea();
p[0].getArea();
问题 2 :(这是“奇技淫巧”,很可能你编一辈子程序也不会遇到)
void (*(*papf)[2])(int);
这个papf是什么东西(摘自C++ Primer)?
答:(*papf)[2] papf是一个指针,它指向一个数组,这个数组有两个元素
*(*papf)[2] papf是一个指针,它指向一个数组,这个数组有两个元素,且都是指针
*(*papf)[2]() papf是一个指针,它指向一个数组,这个数组有两个元素,且都是函数指针,
*(*papf)[2](int) 并且此函数拥有一个int参数,
void *(*papf)[2](int); ,无返回值
(by LengXAC)
第6节:C++字符串类
第7节:数据域封装
Circle2.h
// radius --> private
// getter/setter
class Circle
{
public:
Circle();
Circle(double);
double getArea();
double getRadius();
void setRadius(double);
private:
double radius_;
};
Circle2.cpp
#include "Circle2.h"
// Construct a circle object
Circle::Circle()
{
radius_ = 1;
}
// Construct a circle object
Circle::Circle(double newRadius)
{
radius_ = newRadius;
}
// 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 newRadius)
{
radius_ = (newRadius >= 0) ? newRadius : 0;
}
第8节:变量作用域与this指针
HideDataField.cpp
#include <iostream>
using namespace std;
class Foo
{
public:
int x; // data field
int y; // data field
Foo()
{
x = 10;
y = 10;
}
void p()
{
int x = 20; // local variable
cout << "x is " << x << endl;
cout << "y is " << y << endl;
}
};
int main()
{
Foo foo;
foo.p();
return 0;
}
问题 :
当初设计C++语言时,为什么要有this指针?没有它行不行?
答:当参数名与数据域成员名相同时,而private的变量名后没有下划线,容易与参数的名字混淆。所以用this指针明确所属。this指针等于该类对象的地址,在对象内,函数非常难获得本对象的地址,所以,this指针还是很有必要的。
(by 侯云锋 已知黄昏晚)
第9节:对象作为函数参数
PassObjectToPointer.cpp
#include <iostream>
#include "Circle2.h"
using namespace std;
void printCircle(Circle *c) {
cout << "The area of the circle of " <<
c->getRadius() << " is " << c->getArea() << endl;
}
int main() {
Circle myCircle(5.0);
printCircle(&myCircle);
return 0;
}
PassObjectByValue.cpp
#include <iostream>
#include "Circle2.h"
using namespace std;
void printCircle(Circle c) {
cout << "The area of the circle of " <<
c.getRadius() << " is " << c.getArea() << endl;
}
int main() {
Circle myCircle(5.0);
printCircle(myCircle);
return 0;
}
PassObjectByReference.cpp
#include <iostream>
#include "Circle2.h"
using namespace std;
void printCircle(Circle &c) {
cout << "The area of the circle of " <<
c.getRadius() << " is " << c.getArea() << endl;
}
int main() {
Circle myCircle(5.0);
printCircle(myCircle);
return 0;
}
问题:在为函数传参时, 何时用引用,何时用指针呢?
答:一般来说,能用引用尽量不用指针。引用更加直观,更少出现意外的疏忽导致的错误。
指针可以有二重、三重之分,比引用更加灵活。有些情况下,例如使用 new 运算符,只能用指针。
指针和引用的区别
第10节:对象数组
TotalArea.cpp
#include <iostream>
#include "Circle2.h"
using namespace std;
// Add circle areas
double sum(Circle circleArray[], int size)
{
// Initialize sum
double sum = 0;
// Add areas to sum
for (int i = 0; i < size; i++)
sum += circleArray[i].getArea();
return sum;
}
// Print an array of circles and their total area
void printCircleArray(Circle circleArray[], int size)
{
cout << "Radius\t\t" << "Area" << endl;
for (int i = 0; i < size; i++)
{
cout << circleArray[i].getRadius() << "\t\t" <<
circleArray[i].getArea() << endl;
}
cout << "-----------------------------------------" << endl;
// Compute and display the result
cout << "The total areas of circles is \t" <<
sum(circleArray, size) << endl;
}
int main()
{
const int SIZE = 10;
// Create a Circle object with radius 1
Circle circleArray[SIZE];
for (int i = 0; i < SIZE; i++)
{
circleArray[i].setRadius(i + 1);
}
printCircleArray(circleArray, SIZE);
return 0;
}
第11节:类抽象与封装
第12节:构造函数初始化列表
NoDefaultConstructor1.cpp
class Time
{
public:
Time(int hour, int minute, int second)
{
// Code omitted
}
private:
int hour;
int minute;
int second;
};
class Action
{
public:
Action(int hour, int minute, int second)
{
time = Time(hour, minute, second);
}
private:
Time time;
};
int main() {
return 0;
}
无法编译通过
相关代码修改为
Action(int hour, int minute, int second)
: time(hour, minute, second)
{
}