type
Post
status
Published
date
Sep 5, 2025
slug
c++_oop
summary
使用的课程是浙江大学翁恺的C++面向对象设计
tags
计算机科学
category
学习笔记
icon
password

1 什么是面向对象

What is an object?

  • Object = Entity
  • Object is variable in programming language.
  • Object = Attributes + Service
  • Object = Data(the properties + status) + Options(the functions)

What is object-oriented?

  • Design
  • Implementations

Objects send messsges

  • message are
    • composed by sender
    • interpreted by receiver
    • implemented by methods
  • message may
    • cause receiver to change status
    • return results

Class vs. Object

  • Class defines object, object is a class

OOP Characteristics

  1. Everything is an object.
  1. A program is a bunch of objects telling each other what to do by sending messages.
  1. Each object has its own memory made up of other objects.
  1. Every object has a type.
  1. All objects of a particular type can receive the same messages.

Functions of interface

  • Communication
  • Protection(hidden implementation)

Encapsulation(封装)

  • bundle data and methods dealing with these data together in an object
  • Hide the details of the data and the action
  • Restrict only access to the publicized methods.

Abstract

Ignore some details of an object.
For example: Clock
notion image
has two parts:
notion image
so we have:

2 类的结构

Example: Ticket Machine

#TicketMachine.h
Class Declaration and prototypes in the class are in the header file(.h)
Header = interface
#TicketMachine.cpp
All the bodies of these functions are in the source file(.cpp)
#main.cpp
  • ::resolver:域的解析符
    • <Class Name>::<function name>
    • ::<function name> 全局函数

c++ 程序的结构

notion image
这意味着预处理器将#include的内容直接插入到.cpp文件前方,这个文件再被编译器编译
因此不能在.h文件中进行定义,否则可能会发生重复定义,因此.h文件中全局变量的declaration:
只有一下东西是声明:
  • extern variables
  • function prototypes(without {})
  • class/struct declaration

头文件

#include

  • 在当前目录查找
  • 在特定目录查找

标准头文件结构

它的意义是.h被多次include时,由于第一次宏已经被定义,因此后面的include被忽略,从而阻止类的声明重复出现。

成员变量

c++中有三种变量:
  • Fields:成员变量,与函数无关,只要类存在,在类的所有函数都可以使用
  • Parameters:参数
  • Local variables:本地变量,与函数有关
后两者是一个东西,即本地存储,函数执行完则释放。
对于成员变量,有例子:
我们注意到,当调用f函数时,函数知道该对a的成员变量进行操作,就像在结构中传入了a的地址一样,这是由于c++语言设计,是的类的所有的函数都传入了this指针,即:

构造函数(constructor)

特征:
  • 名字与类的名字相同
  • 没有返回类型
  • 在对象创建时调用
  • 构造函数有其参数传入;

The default constructor

默认构造函数是指不带参数的构造函数,例如以上的X,如果定义类时没有声明构造函数,则系统会自动创建默认构造函数。

Initialize list

在构造函数后直接给出成员变量的初始值从而完成初始化,如下:
这种初始化和在构造函数内进行初始化的区别在于,对于类初始化时直接构造调用的是拷贝构造函数,而不是先调用默认构造函数,再赋值,如下:
但是对于基本数据类型如int,性能上则没什么改进。

析构函数(destructor)

new & delete

new和delete是c++语言用来申请内存和释放内存的运算符,new返回的是指针,例如:
值得注意的是,new申请内存时同时记录了这个变量如p的开头的地址和字节长度,因此在delete时也会根据这个记录进行释放,因此如果申请的是一个数组,如下:

访问限制

  • public:任何人都能访问
  • private:只有这个类的成员函数能够访问,不同对象的成员函数也可以互访
    • friends:朋友可以访问private内的东西

3 OOP

Composition

使用已有的对象拼装出新的对象,例子如下:

Inheritance

Inheritance allows sharing of design for
  • member data
  • member functions
  • interfaces
for example:
notion image
in this picture, person is superset of student, which means student has more data and ability than person.
we have more notion to describe the relate:
notion image
the particular code implementation is below:

Example: Employee and Manager

关键点:
  • 同名隐藏,子类的同名函数不会重载,父类的同名函数遭到隐藏
  • 子类构造函数初始化时调用父类的构造函数

Function overloading

以上呈现了函数重载的基本逻辑

Default Argument

值得注意的是,默认参数只能写在函数原型。

Inline

Inline函数是一种C++优化机制,它提示编译器在调用点直接展开函数代码,而不是执行常规的函数调用。
正常函数调用需要进行以下操作:
  • 参数压栈
  • 保存程序计数器
  • 跳转到函数代码位置
  • 执行函数代码
  • 返回到调用点
  • 提取返回值
对于非常简短的函数,这些调用开销可能超过函数本身的执行时间。使用inline可以消除这些开销。
值得注意的是:
  • inline本身是declaration,因此inline应该放在.h而非.cpp中
  • 如果函数过于巨大或迭代,编译器会拒绝inline
  • 成员函数如果在声明时直接写出body则是inline
  • 小的或者大量调用的适合作为inline

Const

  • Const意味着变量不能变化
  • Const仍然是变量,只是编译器保证其不发生变化
  • Pointers and Const
Skip

Declaring references

three types of data:
Reference means declares a new name for an existing object:
  • Reference must be initialized when defined, except for declaration.
  • Initialing established a binding
    • in declaration: binding don’t change at run time
    • as a function argument
  • The target of a reference must have a location!
for example:
Reference vs. Pointer
References
Pointers
can’t be null
can be set to null
are dependent on an existing variables, they are an alias for an variable
pointer is independent of existing objects
can’t change to a new “address” location
can change to point to a different address
however reference is actually a kind of implementation of pointer!

Upcasting

We know that if class D is derived from class B:
  • An object of type D can be assigned to an object of type B.
  • A pointer to D can be assigned to a pointer to B.
  • A reference to D can be assigned to a reference to B.
This is possible because, from the pointer's perspective, the memory layout of the derived class D is an extension of the base class B. The B subobject resides at the beginning of any D object. Therefore, a pointer to B can point to the start of a D object and correctly access all the members defined in B.
particular code is below:

Polymorphism

Let’s take look at this example:
In this case, we define some function which have same name, but when we use this function by pointer, the function seemed to know it should use which version, we call this feature polymorphism.
Polymorphism has two features:
  • Upcasting: means we treat the derived class as the base one
  • Dynamic binding: call the function as the object
    • compare to static binding: call the function as the code
In the case, p is a pointer as its static type, however the object the p point to shows p is dynamic type.
We use the key word virtual to let pointer work as a dynamic type.
But how polymorphism works? Let’s take look the code below:
In this case we know that the class with “virtual” is bigger than the one without it, in fact there is a pointer call vptr at the top of the “virtual class”, which point to vtable.
notion image
Deferent object share same vptr(copy):
Deferent class has deferent vptr:
When we use int*p = &a to get vptr of a, p is the address of vptr, and *p value of vptr, which means the address of table of virtual function. So if we change the *p, we factly change the vptr itself, this is very dangerous.
Another problem is the derived class mustn’t have a function return the value:
Because returning the value of derived class may slice the class for the class is deferent, but for point or reference, it is safe.

The Copy Constructor

Let’s take look an example:
It is strange that after call f(HowMany x) ,objectcount is still 1, however, the destructor was called, which means x and f is truly constructed.
This is because the c++ automatically generate a function call the copy constructer, which copy the member variables.
there is a very typical error in declaration of copy constructor:
If there is pointer or reference, c++ would generate pointer or reference which point same thing, this may cause error:
This error shows that the memory is freed twice, for the reason that the default copy constructor just makes new name point to the same address.
So we need to write the copy constructor by ourself:
there is some cases we always need it:
the case 3 is special, let’s take look an example:
Compare to func2, in func1, function write was called, so that the ROV can’t optimize p, so error happened.(In C++ 11, ROV optimize the func1 too!)
 

Static

Static in C++ has two basic meaning:
  • Static Storage: allocated once at a fixed address,(allocate v.分配, fixed adj.固定的)which means as it is created, it won’t be deleted before end of the program.
  • Visibility of a name: internal linkage, means the variables or functions is invisible out of the .cpp file where they were defined.
    • extern in c++ could help found the definition of variables and functions in other .cpp file.
There are some cases:
  • Static in function:
  • Static in object:
  • Global object:
  • Static member variable:
Directly executing this program will get error:
ld: symbol(s) not found for architecture arm64
This is because the equation static int i; is just a declaration, in common case, without static, i will automatically be defined when the object was created, but in this case, i is a static int, which means that i is in global storage. So we need to define i out of Class:
And it’s not allow to use initialization list to initialize i, because i must be initialized at where it was defined.
  • Static member function

Overloading operators

Skip

Templates

In some case two things have same demand but we can’t easily use class to describe them, this is when templates help.
Template use types as parameters, there are four types of templates:
  • function templates
  • class templates
  • template functions
  • template classes
For example: swap template
Overloading Rules:
  • check first for unique function match
  • then check for unique function template
  • then do overloading on functions
In some case template function didn’t have parameters, we must explicitly point out the type:
For template classes, an example is below:
For template classes, we must point out the type when we construct objects. There is another example:

Exceptions

skip

Streams

what is a stream:
notion image
stream has two feature:
  • has one direction
  • 1 dimension
notion image
we have seen three operator before:
  • Extractors
    • read a value from a stream
    • overload the >> operator
  • Inserters
    • insert a value into a stream
    • overload the << operator
  • Manipulators
    • change the stream state
We have two kinds of stream in C++:
  • Text stream
  • Binary stream
Overload the stream operator:
the return must be isstream because we have the expression
相关文章
Chapter 1 前馈神经网络Python Review
Loading...