lecture8 Template Classes + Const Correctness

lecture8 Template Classes + Const Correctness

Classes Recap

“Template Class: A class that is parametrized over some number of types. A class that is comprised of member variables of a general type/types.” 模板类:在一定数量的类型上参数化的类。由通用类型的成员变量组成的类。

“Writing a Template Class: Syntax” 编写模板类:语法

// mypair.h
template<typename First, typename Second> class MyPair{
	public:
		First getFirst();
		Second getSecond();
		void setFirst(First f);
		void setSecond(Second f);
	private:
		First first;
		Second second;
};

“Use generic typenames as placeholders!” 使用通用类型名称作为占位符!

“Implementing a Template Class: Syntax” 实现模板类:语法

// mypair.cpp
#include "mypair.h"

template<class First, typename Second>
First Mypair<First, Second>::getFirst(){
	return first;
}

Template Classes

“Member Types” 成员类型

std::vector<int> a = {1, 2};
std::vector<int>::iterator it = a.begin();
  • 在这里iteratorvector 的成员类型

“Member Types: Syntax” 成员类型:语法

// vector.h
template<typename T> class vector{
	public:
	using iterator = T*;

	iterator begin();
}
// vector.cpp
typename vector<T>::iterator vector<T>::begin() {}

“Aside: Type Aliases” 类型别名

  • 可以在应用代码中使用using type_name=type
  • 当在类接口中使用类型别名时,它会定义一个简洁类型就像vector::iterator
  • 当在应用代码中使用时(比如main.cpp)会在范围内为type 创建另一个名字

Const Correctness

“const: keyword indicating a variable, function or parameter can’t be modified” const:关键字,表示变量、函数或参数不能被修改

“Recall: Student class”

// student.h
class Student {
	public:
	std::string getName();
	void setName(string name);
	int getAge();
	void setAge(int age);

	private:
	std::string name;
	std::string state;
	int age;
};
// student.cpp
#include "student.h"
std::string Student::getName(){
	return name;
}
void Student::setName(string name) {
	this->name = name;
}
int Student::getAge() {
	return age;
}
void Student::setAge(int age) {
	if(age>=0) {
		this->age = age;
	}
	else error("Age cannot be negative!");
}

“Using a const Student”

//main.cpp
std::string stringify(const Student& s) {
	return s.getName() + " is " + std::to_string(s.getAge()) + " years old.";
}
// complie error!
  • 编译器不知道getNamegetAge 会改变s
  • 我们需要保证将以上函数设为const function
  • add 假如函数签名后
// student.h
class Student {
	public:
	std::string getName() const;
	void setName(string name);
	int getAge() const;
	void setAge(int age);

	private:
	std::string name;
	std::string state;
	int age;
};
// student.cpp
#include "student.h"
std::string Student::getName()const{
	return name;
}
void Student::setName(string name) {
	this->name = name;
}
int Student::getAge() const{
	return age;
}
void Student::setAge(int age) {
	if(age>=0) {
		this->age = age;
	}
	else error("Age cannot be negative!");
}

“const-interface: All member functions marked const in a class definition. Objects of type const ClassName may only use the const-interface.” const-interface:类定义中标记为 const 的所有成员函数。 const ClassName 类型的对象只能使用 const 接口。

“Making StrVector‘s const-interface” 制作 StrVector 的 const 接口

class StrVector {
public:
	using iterator = std::string*;
	const size_t kInitialSize = 2;

	size_t size();
	bool empty();
	std::string& at(size_t index);
	void insert(size_t pos, const std::string& elem);
	void push_back(const std::string& elem);

	iterator begin();
	iterator end();
}
class StrVector {
public:
	using iterator = std::string*;
	const size_t kInitialSize = 2;

	size_t size() const;
	bool empty() const;
	std::string& at(size_t index);
	const std::string& at(size_t indx) const;
	void insert(size_t pos, const std::string& elem);
	void push_back(const std::string& elem);

	iterator begin();
	iterator end();
}

“Should begin() and end() be const?” begin() 和 end() 应该是 const 吗?

void printVec(const StrVector& vec) {
	cout<<"{ ";
	for(auto it = vec.begin(); it != vec.end(); ++it) {
		cout<<*it<<endl;
	}
	cout<<" }"<<endl;
}

看起来将其设为const 是可行的,但会发生什么错误?

void printVec(const StrVector& vec) {
	cout<<"{ ";
	for(auto it = vec.begin(); it != vec.end(); ++it) {
	*it = "dont mind me modifying a const vector :D";”
	}
	cout<<" }"<<endl;
}

以上代码会编译通过!因为begin()end() 并不会显式改变vec,但是这个itertor 确实可以改变的

“Problem: we need a way to iterate through a const vec just to access it” 问题:我们需要一种方法来迭代 const vec 来访问它(仅限访问与迭代但是不能更改)

“Solution: cbegin() and cend()” 解决方案:cbegin() 和 cend()

class StrVector {
public:
	using iterator = std::string*;
	using const_iterator = const std::string*;
	const size_t kInitialSize = 2;

	size_t size() const;
	bool empty() const;
	std::string& at(size_t index);
	const std::string& at(size_t indx) const;
	void insert(size_t pos, const std::string& elem);
	void push_back(const std::string& elem);

	iterator begin();
	iterator end();
	const_iterator begin() const;
	const_iterator end() const;
}

“Abilities of Iterator Permutations” 迭代器排列的能力

Iterator Type Increment Iterator? Change underlying value?
iterator Y Y
const_iterator Y N
const iterator N Y
const const_iterator N N

可以这么理解:

string* 可以看作数组的头指针即数组

const string* 是将数组声明为常数数组内部不能更改,但是数组迭代可以

const iterator 是将指针所指空间声明常量,不能迭代(会改变指针所指位置)但是可以更改指针空间内存的东西

const const_iterator 是将数组和指针所指地址均视作常量均不能更改

“const iterator vs const_iterator: Nitty Gritty”

using iterator = std::string*;
using const_iterator = const std::string*;

const iterator it_c = vec.begin();//string * const, const ptr to non-const obj
*it_c = "hi"; //OK! it_c is a const pointer to non-const object
it_c++; //not ok! can’t change where a const pointer points!

const_iterator c_it = vec.begin(); //const string*, a non-const ptr to const obj
c_it++; // totally ok! The pointer itself is non-const
*c_it = "hi" // not ok! Can’t change underlying const object
cout << *c_it << endl; //allowed! Can always read a const object, just can't change

//const string * const, const ptr to const obj
const const_iterator c_it_c = vec.begin();
cout << c_it_c << " points to " << *c_it_c << endl; //only reads are allowed!
c_it_c++; //not ok! can’t change where a const pointer points!
*c_it_c = "hi" // not ok! Can’t change underlying const object
posted @ 2024-05-05 23:57  viewoverlook  阅读(5)  评论(0编辑  收藏  举报