review
- a class bundles data and methods for an object together
- header file contains interface ,declaritions
- cpp contains implementation,definitions
- what is this? a pointer to the current class instance
template classes
how can we generalize across different types?
历史
之前使用宏定义
#define GENERATE_VECTOR(MY_TYPE)//preprocessor macro runs before compile
class MY_TYPE##Vector{
public:
MY_TYPE& at(size_t index);
void push_back(const MY_TYPE& elem);
private:
MY_TYPE*elems;
size_t logical_size;
size_t array_size;
}
#include"grandmas_template.h"
GENERATE_VECTOR(int)//code generation
intvector v1;
v1.push_back(5);
宏的问题
- clunky syntax
- hard to type check
- 忘记叫宏了或者不止叫一次
key idea:templates automate code generation
-
a type is a template instantiation
-
typename is interchangeable
template<typename T>
class vector{};
template<size_t N>
class sizetemplate{};
sizetemplate<5> s;
template<bool B>
class booltemplate{};
booltemplate<true> b;
template<typename T,std::size_t N>
struct std::array{```};
//an array of exactly 5strings
std::array<std::string,5> arr;
//使用数组而不是向量的原因是避免堆分配,编译器会exactly知道一个数组array<string,5>需要多大的空间,成为栈分配
一些奇怪点
- msutcopytemplate<…>syntax in.cpp
-
.h must include .cpp at bottom of file.与模板生成代码实现如何在编译器以及链接器中实现有关 (non-template classes :the .cpp file includes the .h file)when instantiating templates, the compiler must have full knowledge of both the declaration (this file)and the definitions (.cpp file) of the template https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl
-
typename is the same as class
const correctness
- const 函数 不修改对象
- inside a const method,this has type const vector<\T>*
the const interface
- objects marked as const can only make use of the const interface
- the const interface are the functions that are const in an object
const overloading
two versions of at method one version gets called for const instances,another gets called for non-const instances
template<class T>
class vector{
public:
const T& at(size_t index) const;
T& at(size_t index);
};
return elems[index];
implementing findelement
T& findelement(const T& value);
const T& findelement(const T& value) const;
template<typename T>
T& vector<T>::findelement(const T& value){
for(size_t i=0;i<logical_size;i++)
{if(elems[i]==elem)return elems[i];}
throw std::out_of_range("element not found")
}
const version thesame
- casting:the process of converting one type to another
- const_cast allows us to cast away the const-ness of a variable
- usage:const_cast
(expression)
template<typename T>
const T&vector<T>::findelement(const T&value) const{
return const_cast<vector<T>&>(*this).findelemnt(value);
}
//不再冗余?
- const_cast casts away the const
- this dereferences a const vector<\T>** ,giving us a const-ref
- vector<\T>& is a non-const reference .the type we would like
when to use const_cast?
- never?
- const_cast makes an entire object mutable
mutable keywords
- circumvents const protections
struct mutablestruct{
int donttouchthis;
mutable double icanchange;
};
const mutablestruct cm;
//cm.donttouchthis=42;//notallowed,cm is const
cm.icanchange=3.14;
- mutable example:storing debug info
struct cameraray{
Point origin;
Direction direction;
mutable color debugcolor;
}
void renderray(const cameraray&ray){
ray.debugcolor=color.yellow;
}
recap
- template classes generalize logic across types
- const makes an entir object read-only
- mark methods const when they don't modify the object
- const_cast and mutable can circumvent compiler in rare cases