目录
写在前面
模板类中的静态成员变量
项目练习:万能容器Vector的实现
总结
致谢
今天,为了这个周末的seminar,博主花了整个白天调case。本来计划今晚继续调case,但我突然意识到今天的cpp还没学。因此,我决定晚上在实验室抽出一些时间给cpp。中午休息时,我简短地学习了一些关于异常处理的知识,但我还没有完全弄清楚如何有效地总结和应用这些知识。然后我想起了昨晚在学习泛型编程时,我只看了视频,却没有实际动手练习。所以本文就是关于昨晚学习的泛型编程的部分琐碎知识以及相应的一个简单的实战练习。
/*
* Created by herryao on 1/21/24.
* Email: [email protected]
* Sungkyunkwan Univ. Nano Particle Technology Lab(NPTL)
*/
#ifndef PROJECT02_A_H
#define PROJECT02_A_H
template
class A{
public:
A(T t = 0){
this->t_ = t;
}
T& getT(){
return this->t_;
}
A operator+(const A& other);
//static member variables
static int count;
private:
T t_;
//declaration a friend function to achieve the addition operation
//friend function is independent on the class so the template type need to clarify
template
friend A addA(const A&a, const A&b);
};
#endif//PROJECT02_A_H
/*
* Created by herryao on 1/21/24.
* Email: [email protected]
* Sungkyunkwan Univ. Nano Particle Technology Lab(NPTL)
*/
#include "A.h"
//definition of the function
template
//all the class name in the definition need to clarify the template type
A A::operator+(const A& other){
//While within the function body, with or without explict declaration, it is flexible
A temp = A(this->t_ + other.t_);
return temp;
}
template
A addA(const A&a, const A&b){
A temp = A(a.t_ + b.t_);
return temp;
}
//static member variables
template int A::count = 0;
让我们来测试我们的静态成员变量在不同类型下的行为。通常,我们认为一旦静态成员变量初始化,任何对象对其的修改都应该是共享的。基于这个理解,我们首先初始化了一个全局静态变量,值为0。接着,我们创建了三种不同类型的对象:int、char和double。每个对象都对这个静态成员变量进行了修改,随后我们打印了每个对象的静态成员变量的值。这样做的目的是为了观察,是否如我们所预期的那样,不同类型的对象共享同一个静态成员变量。
void test_4_static_template(){
A a(666), b(888);
a.count = 80;
A c('a');
A d(10.);
//static member in template class are independent regarding different type, will within same type it follows the protocol of the static member
std::cout << "a: " << a.count << "\tb: " << b.count << "\tc: " << c.count << "\td: " << d.count << std::endl;
c.count = 100;
std::cout << "a: " << a.count << "\tb: " << b.count << "\tc: " << c.count << "\td: " << d.count << std::endl;
}
/media/herryao/81ca6f19-78c8-470d-b5a1-5f35b4678058/work_dir/Document/computer_science/QINIU/projects/week02/day07/project02/cmake-build-debug/project02
a: 80 b: 80 c: 0 d: 0
a: 80 b: 80 c: 100 d: 0
Process finished with exit code 0
/*
* Created by herryao on 1/22/24.
* Email: [email protected]
* Sungkyunkwan Univ. Nano Particle Technology Lab(NPTL)
*/
#ifndef PROJECT01_VECTOR_H
#define PROJECT01_VECTOR_H
#include
template
class Vector {
public:
//constructor
Vector(size_t length);
//destructor
~Vector();
Vector(const Vector& vector);
Vector& operator=(const Vector&obj);
T operator[](int idx) const;
T& operator[](int idx);
template
friend std::ostream& operator<< (std::ostream& os, const Vector& obj);
[[nodiscard]]size_t getLength()const;
private:
T* list_;
size_t length_;
};
std::ostream& operator<< (std::ostream& os, const Vector& obj);
#endif//PROJECT01_VECTOR_H
/*
* Created by herryao on 1/22/24.
* Email: [email protected]
* Sungkyunkwan Univ. Nano Particle Technology Lab(NPTL)
*/
#include "Vector.h"
template
Vector::Vector(size_t length) {
this->list_ = new T[length];
if (this->list_ != nullptr) {
this->length_ = length;
} else
throw "unable to malloc the heap";
}
template
Vector::~Vector() {
if(this->list_!= nullptr){
delete []this->list_;
this->list_ = nullptr;
}
}
template
Vector::Vector(const Vector &other) {
this->list_ = new T[other.length_];
if(this->list_ != nullptr){
for(int i=0; ilist_[i] = other.list_[i];
}
this->length_ = other.length_;
}
}
template
Vector &Vector::operator=(const Vector &obj) {
if(this != &obj){
if(this->list_ != nullptr){
delete []this->list_;
}
this->list_ = new T[obj.length_];
if(this->list_!= nullptr){
for(int i=0; ilist_[i] = obj.list_[i];
}
this->length_ = obj.length_;
}
}
return *this;
}
template
T &Vector::operator[](int idx) {
if(idx >= 0&& idxlength_){
return this->list_[idx];
}
}
template
T Vector::operator[](int idx) const{
if(idx >= 0&& idxlength_){
return this->list_[idx];
}
}
template
std::ostream& operator<< (std::ostream& os, const Vector& obj){
for(int i=0; i
size_t Vector::getLength() const {
return this->length_;
}
/*
* Created by herryao on 1/22/24.
* Email: [email protected]
* Sungkyunkwan Univ. Nano Particle Technology Lab(NPTL)
*/
#ifndef PROJECT01_STUDENT_H
#define PROJECT01_STUDENT_H
#include
#include
#include
#include
class Student {
public:
Student();
Student(const char*name, int age);
~Student();
void print();
Student(const Student& other);
Student& operator =(const Student&other);
friend std::ostream& operator << (std::ostream& os, const Student* pst);
friend std::ostream& operator <<(std::ostream& os, const Student& st);
private:
char* name_;
int age_;
};
std::ostream& operator << (std::ostream& os, const Student* pst);
std::ostream& operator <<(std::ostream& os, const Student& st);
#endif//PROJECT01_STUDENT_H
/*
* Created by herryao on 1/22/24.
* Email: [email protected]
* Sungkyunkwan Univ. Nano Particle Technology Lab(NPTL)
*/
#include "Student.h"
Student::Student() {
this->name_ = new char[strlen("unknown")+1];
if(this->name_){
strcpy(this->name_, "unknown");
this->age_ = 0;
}
}
Student::Student(const char *name, int age) {
this->name_ = new char[strlen(name)+1];
if(this->name_){
strcpy(this->name_, name);
this->age_ = age;
}
}
Student::~Student() {
if(this->name_){
delete[]this->name_;
this->name_ = nullptr;
}
}
Student &Student::operator=(const Student &other) {
if(this != &other){
if(this->name_){
delete[]this->name_;
}
this->name_ = new char[strlen(other.name_)+1];
if(this->name_){
strcpy(this->name_, other.name_);
this->age_ = other.age_;
}
}
return *this;
}
Student::Student(const Student& other){
this->name_ = new char[strlen(other.name_)+1];
if(this->name_){
strcpy(this->name_, other.name_);
this->age_ = other.age_;
}
}
void Student::print() {
std::cout << "student name: " << this->name_ << " age: " << this->age_ << std::endl;
}
std::ostream& operator <<(std::ostream& os, const Student* pst){
os << "student name: " << pst->name_ << " age: " << pst->age_ << std::endl;
return os;
}
std::ostream& operator <<(std::ostream& os, const Student& st){
os << "student name: " << st.name_ << " age: " << st.age_ << std::endl;
return os;
}
void check_4_obj(){
Student st1("gigi", 25);
Student st2("bigbean", 25);
Student st3("asifmuhammad", 24);
Student st4("gulgunbahit", 24);
Student st5("panghu",1);
Vector lstu(5);
lstu[0] = st1;
lstu[1] = st2;
lstu[2] = st3;
lstu[3] = st4;
lstu[4] = st5;
std::cout << lstu;
std::cout << "here template by obj done" << std::endl;
for(int i=0; i
/media/herryao/81ca6f19-78c8-470d-b5a1-5f35b4678058/work_dir/Document/computer_science/QINIU/projects/week03/mon/project01/cmake-build-debug/project01
student name: gigi age: 25
student name: bigbean age: 25
student name: asifmuhammad age: 24
student name: gulgunbahit age: 24
student name: panghu age: 1
here template by pointer done
student name: gigi age: 25
student name: bigbean age: 25
student name: asifmuhammad age: 24
student name: gulgunbahit age: 24
student name: panghu age: 1
Process finished with exit code 0
void check_4_ptr(){
Student st1("gigi", 25);
Student st2("bigbean", 25);
Student st3("asifmuhammad", 24);
Student st4("gulgunbahit", 24);
Student st5("panghu",1);
Vector lpstu(5);
lpstu[0] = &st1;
lpstu[1] = &st2;
lpstu[2] = &st3;
lpstu[3] = &st4;
lpstu[4] = &st5;
std::cout << lpstu;
std::cout << "here template by pointer done" << std::endl;
for(int i=0; iprint();
}
}
其调用后的输出如下,可以看到终于不再是长长的一串数据输出了,和普通对象的容器实现了相同的功能:
/media/herryao/81ca6f19-78c8-470d-b5a1-5f35b4678058/work_dir/Document/computer_science/QINIU/projects/week03/mon/project01/cmake-build-debug/project01
student name: gigi age: 25
student name: bigbean age: 25
student name: asifmuhammad age: 24
student name: gulgunbahit age: 24
student name: panghu age: 1
here template by obj done
student name: gigi age: 25
student name: bigbean age: 25
student name: asifmuhammad age: 24
student name: gulgunbahit age: 24
student name: panghu age: 1
Process finished with exit code 0