C++认为C的东西都可以封装一下,实现定制、隐藏、易用、安全

C++的哲学就是把所有东西都封装一下,提供访问控制(安全控制),提供更多的方法和功能。这种封装也可以称为抽象,通过更高一层的抽象来实现隐藏和安全。

0 结构体封装和控制:访问控制+函数指针+构造析构

1 原生指针封装和定制:迭代器、智能指针

2 C风格字符串封装和定制:string类

3 函数封装和定制:函数对象

4 原生数组封装和控制:array类、vector类

5 栈封装和控制:stack类

6 浮点数也可以封装和定制,可以定义一下浮点数比较方式

7 整数也可以封装和定制,可以判断一下是否上溢和下溢

8 封装malloc+构造函数:new

9 FILE封装一下:stream类

0 结构体封装和控制:访问控制与构造析构

参考:

编程基础:从面向过程到面向对象,从结构体到类

C++的逐层抽象:从结构体到类、模板

1 原生指针封装和定制:迭代器、智能指针

参考:

C++|简单模仿STL中容器的迭代器的底层实现机制

C++|从使用指针的迭代操作到使用模板技术的指针类(迭代器)

详解C++四个智能指针的使用和实现

C++|类封装如何提升安全和可维护性,以智能指针封装裸指针为例

C++|引用计数与shared_ptr智能指针(以实现String类为例)

2 C风格字符串封装和定制:string类

#include 
#include 

class String
{
public:
    String(const char* cstr = 0);
    String(const String& str);
    String& operator=(const String& str);
    ~String(){
        delete[] m_data;
    }
    char* get_c_str() const{
        return m_data;
    }
private: char* m_data;
};

String::String(const char* cstr)
{
    if(cstr)
    {
        m_data = new char[strlen(cstr)+1];
        strcpy(m_data,cstr);
    }
    else {
        m_data = new char[1];
        *m_data = '\0';
    }
}

String::String(const String& str)
{
    m_data = new char[strlen(str.m_data)+1];
    strcpy(m_data,str.m_data);
}

String& String::operator=(const String& str)
{
    if(this == &str)
        return *this;
    delete[] m_data;
    m_data = new char[strlen(str.m_data)+1];
    strcpy(m_data,str.m_data);
    return *this;
}

int main()
{
    String str("abc");
    String str2(str);
    String str3 = str2;
    printf("%s
",str3.get_c_str());

    return 0;
}

3 函数封装和定制:函数对象

#include 

class Fib {
public:
    Fib() : a0_(1), a1_(1) {}
    int operator()() {
        int temp = a0_;
        a0_ = a1_;
        a1_ = temp + a0_;
        return temp;
    }
private:
    int a0_, a1_;
};
int main()
{
    Fib fib;
    for(int i=1;i<50;i++)
        printf("%2d  %d
",i,fib());
    getchar();
}

4 数组封装和控制:array类、vector类

#ifndef INTARRAY_H
#define INTARRAY_H

#include  // for assert()

class IntArray
{
private:
    int m_length{};
    int* m_data{};

public:
    IntArray() = default;

    IntArray(int length):
        m_length{ length }
    {
        assert(length >= 0);
        if (length > 0)
            m_data = new int[length]{};
    }
	IntArray(std::initializer_list list) // allow IntArray to be initialized via list initialization
		: IntArray(static_cast(list.size())) // use delegating constructor to set up initial array
	{
		// Now initialize our array from the list
		int count{ 0 };
		for (auto element : list)
		{
			m_data[count] = element;
			++count;
		}
	}
    ~IntArray()
    {
        delete[] m_data;
        // we don't need to set m_data to null or m_length to 0 here, since the object will be destroyed immediately after this function anyway
    }

    void erase()
    {
        delete[] m_data;
        // We need to make sure we set m_data to nullptr here, otherwise it will
        // be left pointing at deallocated memory!
        m_data = nullptr;
        m_length = 0;
    }

    int& operator[](int index)
    {
        assert(index >= 0 && index < m_length);
        return m_data[index];
    }

    // reallocate resizes the array.  Any existing elements will be destroyed.  This function operates quickly.
    void reallocate(int newLength)
    {
        // First we delete any existing elements
        erase();

        // If our array is going to be empty now, return here
        if (newLength <= 0)
            return;

        // Then we have to allocate new elements
        m_data = new int[newLength];
        m_length = newLength;
    }

    // resize resizes the array.  Any existing elements will be kept.  This function operates slowly.
    void resize(int newLength)
    {
        // if the array is already the right length, we're done
        if (newLength == m_length)
            return;

        // If we are resizing to an empty array, do that and return
        if (newLength <= 0)
        {
            erase();
            return;
        }

        // Now we can assume newLength is at least 1 element.  This algorithm
        // works as follows: First we are going to allocate a new array.  Then we
        // are going to copy elements from the existing array to the new array.
        // Once that is done, we can destroy the old array, and make m_data
        // point to the new array.

        // First we have to allocate a new array
        int* data{ new int[newLength] };

        // Then we have to figure out how many elements to copy from the existing
        // array to the new array.  We want to copy as many elements as there are
        // in the smaller of the two arrays.
        if (m_length > 0)
        {
            int elementsToCopy{ (newLength > m_length) ? m_length : newLength };

            // Now copy the elements one by one
            for (int index{ 0 }; index < elementsToCopy; ++index)
                data[index] = m_data[index];
        }

        // Now we can delete the old array because we don't need it any more
        delete[] m_data;

        // And use the new array instead!  Note that this simply makes m_data point
        // to the same address as the new array we dynamically allocated.  Because
        // data was dynamically allocated, it won't be destroyed when it goes out of scope.
        m_data = data;
        m_length = newLength;
    }

    void insertBefore(int value, int index)
    {
        // Sanity check our index value
        assert(index >= 0 && index <= m_length);

        // First create a new array one element larger than the old array
        int* data{ new int[m_length+1] };

        // Copy all of the elements up to the index
        for (int before{ 0 }; before < index; ++before)
            data[before] = m_data[before];

        // Insert our new element into the new array
        data[index] = value;

        // Copy all of the values after the inserted element
        for (int after{ index }; after < m_length; ++after)
            data[after+1] = m_data[after];

        // Finally, delete the old array, and use the new array instead
        delete[] m_data;
        m_data = data;
        ++m_length;
    }

    void remove(int index)
    {
        // Sanity check our index value
        assert(index >= 0 && index < m_length);

        // If we're removing the last element in the array, we can just erase the array and return early
        if (m_length == 1)
        {
            erase();
            return;
        }

        // First create a new array one element smaller than the old array
        int* data{ new int[m_length-1] };

        // Copy all of the elements up to the index
        for (int before{ 0 }; before  < index; ++before)
            data[before] = m_data[before];

        // Copy all of the values after the removed element
        for (int after{ index+1 }; after < m_length; ++after)
            data[after-1] = m_data[after];

        // Finally, delete the old array, and use the new array instead
        delete[] m_data;
        m_data = data;
        --m_length;
    }

    // A couple of additional functions just for convenience
    void insertAtBeginning(int value) { insertBefore(value, 0); }
    void insertAtEnd(int value) { insertBefore(value, m_length); }

    int getLength() const { return m_length; }
};

#endif
#include 
#include "IntArray.h"

int main()
{
    // Declare an array with 10 elements
    IntArray array(10);

    // Fill the array with numbers 1 through 10
    for (int i{ 0 }; i<10; ++i)
        array[i] = i+1;

    // Resize the array to 8 elements
    array.resize(8);

    // Insert the number 20 before element with index 5
    array.insertBefore(20, 5);

    // Remove the element with index 3
    array.remove(3);

    // Add 30 and 40 to the end and beginning
    array.insertAtEnd(30);
    array.insertAtBeginning(40);

    // Print out all the numbers
    for (int i{ 0 }; i

5 栈封装和定制:stack类

#include 
#include 
#include 
#include 
#include 

using namespace std;

template 
class Stack { 
   private: 
       vector elems;    // elements 
       
   public: 
       void push(T const&);  // push element 
       void pop();               // pop element 
       T top() const;            // return top element 
       
       bool empty() const {      // return true if empty.
           return elems.empty(); 
       } 
}; 

template 
void Stack::push (T const& elem) { 
    // append copy of passed element 
    elems.push_back(elem);    
} 

template 
void Stack::pop () { 
    if (elems.empty()) { 
        throw out_of_range("Stack<>::pop(): empty stack"); 
    }
    
    // remove last element 
    elems.pop_back();         
} 

template 
T Stack::top () const { 
    if (elems.empty()) { 
        throw out_of_range("Stack<>::top(): empty stack"); 
    }
    
    // return copy of last element 
    return elems.back();      
} 

int main() { 
    try {
        Stack         intStack;  // stack of ints 
        Stack stringStack;    // stack of strings 
        
        // manipulate int stack 
        intStack.push(7); 
        cout << intStack.top() <

ref

C++|包装裸指针、裸数组、字符串成智能指针、array类和string类

-End-

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章