标签:style blog http color 使用 os strong io
1.虚指针和虚函数表
1.1 不含有任何数据成员或者虚函数的class或者struct大小为1,含有虚函数的对象在基地址部分有一个vptr,指向虚函数表,因此大小为4个字节。
1.2 动态绑定的原理:假设派生类和基类存在覆盖的关系(基类中定义了虚函数),那么派生类在虚函数表中,会覆盖掉基类相应的虚函数。当程序执行的时候,根据基类指针找到vptr,根据vptr找到vtable,然后找到相应的版本去执行。所以执行的是覆盖的版本,而具体被哪个版本覆盖是由具体的对象类型所决定的,所以才实现了根据对象的具体类型去调用相应的函数(参考资料:http://blog.csdn.net/haoel/article/details/1948051/)。
1.3 当类中含有虚函数的时候(不全面),需要把析构函数设为virtual析构函数。
1.3.1 如下例所示,当用基类的指针指向一个派生类的对象时,基类指针会把该内存空间当做是一个基类的对象,对后面派生类的空间不可见,因此,当析构的时候只析构了基类大小的空间,这就造成了资源释放不完全。
#include <iostream>
using namespace std;
/*
* 基类指针指向子类对象空间
* 释放基类指针时会释放不完全
*/
class Base{
public:
Base(){
cout << "Base..." << endl;
}
~Base(){
cout << "~Base..." << endl;
}
};
class Derived : public Base{
public:
Derived(){
cout << "Derived..." << endl;
}
~Derived(){
cout << "~Derived..." << endl;
}
};
int main(int argc, const char *argv[])
{
Base *bp = new Derived();
delete bp; //这里只调用了基类的析构函数 派生类的地址空间没有被释放
return 0;
}
1.3.2 当把基类的析构函数设为为虚函数时,在回收资源的时候会根据实际的类型动态绑定,将资源全部回收。
1.4 函数声明为virtual,意味着需要由用户去继承,以重新实现。
1.5 不要试图重定义基类的非virtual函数。
1.6 虚函数尤其是纯虚函数,相当于制定了一种约定、契约,凡是继承并改写(或者实现纯虚函数)的子类,都必须遵守这一约定。
#ifndef __THREAD_H__
#define __THREAD_H__
#include <pthread.h>
class Thread{
public:
Thread();
virtual ~Thread(){}
void start();
static void* thread_func(void *);
virtual void run() = 0;
void join();
private:
pthread_t tid;
};
#endif
#include "thread.h"
#include <iostream>
Thread::Thread()
:tid(-1)
{
}
void Thread::start(){
pthread_create(&tid, NULL, thread_func, this);
}
void *Thread::thread_func(void *arg){
Thread *pt = static_cast<Thread *>(arg);
pt->run(); //动态绑定
}
void Thread::join(){
pthread_join(tid, NULL);
}
#include "thread.h"
#include <iostream>
#include <unistd.h>
using namespace std;
/*
* 定义线程类 将执行的函数run定义为纯虚函数
* 由派生类实现不同的操作
*/
class TestThread : public Thread{
public:
void run(){
while(1){
sleep(1);
cout << "hello ..." << endl;
}
}
};
int main(int argc, const char *argv[])
{
TestThread th;
th.start();
th.join();
return 0;
}
2.模板的编写
2.1几个简单的模板
2.1.1 程序,这里要注意 模板使用template关键字,尖括号内的类型定义可以使用typename,也可以定义为常量,即为非类型模板形参。。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
/*
* 两个参数的类型可以不同
*/
template <typename T1, typename T2>
T1 add(const T1 &a, const T2 &b){
return a + b;
}
int main(int argc, const char *argv[])
{
cout << add(2, 2.3) << endl;
return 0;
}
2.1.2 程序2。这里T::size_type *p这句话在模板中存在歧义,可以把T::size_type解释成一种类型,所以这里定义了一个指针p,还可以把T::size_type解释成一个变量,所以这样可以看做乘法。解决方案就是在前面加上typename,来说明这是一个定义,而不是乘法。typename T::size_type *p。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
template <typename T, typename V>
void test(T a, V b){
//这里存在歧义
//T::size_type *p;
typename T::size_type *p;
}
int main(int argc, const char *argv[])
{
test(string("hello"), 8);
return 0;
}
3.2 模板类
3.2.1 编写模板类的注意事项:
a)类的声明和实现放到同一个hpp文件中;
b)所有的函数均为 inline;
c)每个函数在类外实现都要加上模板参数类表;
d)类名要写完整,例如SmartPtr<T>,不能漏掉尖括号,因为SmartPtr不是完整的类。
3.2.2 智能指针类模板
#ifndef __SMART_HPP__
#define __SMART_HPP__
#include <stddef.h>
template <typename T>
class Smartptr{
public:
Smartptr();
Smartptr(T *);
~Smartptr();
void resetPtr(T *); //这里T不能为const
const T *getPtr() const;
T &operator*();
const T &operator*()const;
T *operator->();
const T *operator->()const;
operator bool() const;
private:
Smartptr(const T&);
Smartptr operator= (const T&);
T *ptr_;
};
//智能指针模板类的实现
//每个函数在类外的实现都要加上模板参数列表
template <typename T>
inline Smartptr<T>::Smartptr() //类名包括参数
:ptr_(NULL)
{
}
template <typename T>
inline Smartptr<T>::Smartptr(T* ptr)
:ptr_(ptr)
{
}
template <typename T>
inline Smartptr<T>::~Smartptr(){
delete ptr_;
}
template <typename T>
inline void Smartptr<T>::resetPtr(T *ptr){
if(ptr_ != ptr){
delete ptr_;
ptr_ = ptr;
}
}
template <typename T>
inline const T *Smartptr<T>::getPtr()const{
return ptr_;
}
template <typename T>
inline T &Smartptr<T>::operator*(){
return *ptr_;
}
template <typename T>
inline const T &Smartptr<T>::operator*()const{
return *ptr_;
}
template <typename T>
inline T *Smartptr<T>::operator->(){
return ptr_;
}
template <typename T>
inline const T *Smartptr<T>::operator->() const{
return ptr_;
}
template <typename T>
inline Smartptr<T>::operator bool() const{
return ptr_;
}
#endif
#include "smartptr.hpp"
#include <iostream>
#include <assert.h>
using namespace std;
class Animal{
public:
Animal(){
cout << "Animal ..." << endl;
}
~Animal(){
cout << "~Animal..." << endl;
}
void display(){
cout << "in Animal..." << endl;
}
};
int main(int argc, const char *argv[])
{
Smartptr<Animal> pt(new Animal);
assert(pt); // 这里重载了bool类型
cout << pt.getPtr() << endl;
pt.resetPtr(NULL);
assert(pt == 0);
cout << "------------" << endl;
pt.resetPtr(new Animal);
pt->display();
return 0;
}
3.2.3 队列类模板
#ifndef __QUEUE_H__
#define __QUEUE_H__
#include <stddef.h>
#include <assert.h>
template <typename T>
class Queue; //前向声明 用于 friend class
template <typename T>
class Node{
friend class Queue<T>;
private:
T data_;
Node* next_;
};
template <typename T>
class Queue{
public:
typedef Node<T> *NodePtr; //
Queue();
Queue(const Queue &queue);
Queue &operator=(const Queue &queue);
~Queue();
void push(const T &data);
void pop();
void clear();
const T &top() const;
bool isEmpty()const;
size_t getSize()const;
private:
void copyElements(const Queue &queue);
NodePtr head_;
NodePtr tail_;
size_t size_;
};
template <typename T>
inline Queue<T>::Queue()
:head_(NULL),
tail_(NULL),
size_(0){
}
template <typename T>
inline void Queue<T>::copyElements(const Queue &queue){
NodePtr pCur = queue.head_;
while(pCur != queue.tail_){
push(pCur->data_);
pCur = pCur->next_;
}
}
template <typename T>
inline Queue<T> &Queue<T>::operator=(const Queue &queue){
clear();
copyElements(queue);
}
template <typename T>
inline Queue<T>::Queue(const Queue &queue)
:head_(NULL),
tail_(NULL),
size_(0)
{
copyElements(queue);
}
template <typename T>
inline Queue<T>::~Queue(){
clear();
}
template <typename T>
inline void Queue<T>::push(const T &data){
NodePtr pt = new Node<T>;
pt->data_ = data;
pt->next_ = NULL;
if(isEmpty()){
head_ = tail_ = pt;
}
else{
tail_->next_ = pt;
tail_ = pt;
}
size_++;
}
template <typename T>
inline void Queue<T>::pop(){
assert(!isEmpty());
NodePtr pt = head_;
head_ = head_->next_;
delete pt;
}
template <typename T>
inline void Queue<T>::clear(){
while(!isEmpty()){
pop();
}
}
template <typename T>
inline const T &Queue<T>::top() const{
assert(!isEmpty());
return head_->data_;
}
template <typename T>
inline bool Queue<T>::isEmpty() const{
return head_ == NULL;
}
template <typename T>
inline size_t Queue<T>::getSize()const{
return size_;
}
#endif
#include "queue.hpp"
#include <iostream>
#include <assert.h>
using namespace std;
int main(int argc, const char *argv[])
{
Queue<int> Q;
Q.push(1);
Q.push(2);
while(!Q.isEmpty()){
cout << Q.top() << endl;
Q.pop();
}
return 0;
}
0722-----C++Primer听课笔记----------虚函数和模板,布布扣,bubuko.com
0722-----C++Primer听课笔记----------虚函数和模板
标签:style blog http color 使用 os strong io
原文地址:http://www.cnblogs.com/monicalee/p/3861817.html