const 和non-const成员函数转化

本文探讨了如何在C++中通过static_cast和const_cast处理const和non-const对象间的切换,避免const方法的重复编写,同时解释了为何不直接用const调用non-const的原因。通过实例演示了如何在arr类中实现const和非const版本的operator[]方法。

问题背景:这是针对同一个类的const对象和non-const对象来说的,由于一个const对象只能调用const成员函数,因此有的时候需要同时实现针对const对象和non-const对象的 const方法和non-const方法,大部分时候有着实质等价实现,可以使用non-const版本调用const版本避免代码重复,然后在non-const中再添加自己的内容。

什么是const成员函数,在参数列表后有const关键字的方法为const方法;

解决方案:使用static_cast<const T1>和const_cast<T2>来实现const和非const的切换,这里使用的是non_const调用const版本。

方案问题:为什么不用const调用非const,因为这就会违背const不改变其对象的逻辑,因为非const没有承诺不会改变内容

详细方案:先使用static_cast 将*this从原始类型转化为const类型,再调用函数,使用const_cast移除函数返回值的const性质

代码案例:

#include "iostream"
using namespace std;
class arr{
public:
    int *a;
    int size;
    arr(int size_,int initc){
        a=new int[size_];
        size=size_;
        for(int i=0;i<size_;i++)
            *(a+i)=initc;
        
    };
    ~arr(){
        delete [] a;
        a=nullptr;
        size =0;
#include<iostream> #include<string> #include<cmath> using namespace std; template<typename T> class Stack; template<typename T> class Node { private: T m_data; Node* m_next = nullptr; friend class Stack<T>; public: Node(const T& val) :m_data(val) {} T& date() { return m_data; } //接口函数是很关键的存在,见SList中对<<重载运算符的定义 const T& date() const { return m_data; } //const函数是限定其不能改变类的数据成员,且如果一个对象被声明为 const,则只能调用它的 const 成员函数 Node* next() { return m_next; } Node(const Node&) = delete; Node& operator=(const Node&) = delete; }; template<typename T> class Stack { private: Node<T>* m_top = nullptr; public: Stack() = default; // Stack(const Stack&) = delete; Stack& operator = (const Stack&) = delete; ~Stack() { clean(); } const T& top() { if (empty()) { throw runtime_error("Stack is empty"); } return m_top->m_data; } //其实不返回引用也可以吧 void push(const T &val); void pop(); bool empty() { return m_top == nullptr; } void clean(); }; template<typename T> void Stack<T>::push(const T &val) { Node<T>* node = new Node<T> (val); node->m_next = m_top; m_top = node; } template<typename T> void Stack<T>::pop() { if (empty())return; Node<T>* p = m_top; m_top = m_top->m_next; delete p; } template<typename T> void Stack<T>::clean() { Node<T>* p = nullptr; while (m_top != nullptr) { p = m_top; m_top = m_top->m_next; delete p; } } class Calculator { private: Stack <double> m_num; Stack <char> m_opr; int precedence(const char& s) const; double readNum(string::const_iterator &it); //迭代器就是一种访问string中的各个元素的机制,类似于指针(其底层实现就是指针,同样有解引用(得到对应的数据)、++、- -的操作); bool isNum(string::const_iterator &c)const { //const_iterator是针对const对象的特例化 return *c >= '0' && *c <= '9' || *c == '.'; } void calculate(); public: Calculator() { m_opr.push('#'); } double doit(const string& exp); }; int Calculator::precedence(const char& s) const { switch (s) { case '=':return 0; case'#':return 1; case'(':return 1; case')':return 2; case'+':case'-':return 3; case'*':case'/':return 4; case '^': case '√': case 'L': return 5; } } double Calculator::readNum(string::const_iterator& it) { string t; while (isNum(it)) t += *it++; //对string对象实现拼接,并对迭代器it向后迭代 return stod(t); //string的函数,此条件下只对一个双精度数据处理 } /*int main() //std对两个数据的处理 { std::string numStr = "5646545.32 3.1415923"; size_t idx = 0; double number1 = std::stod(numStr, &idx); double number2 = std::stod(numStr.substr(idx)); getchar(); return 0; }*/ void Calculator::calculate() { char op = m_opr.top(); m_opr.pop(); if (m_opr.top() == '+' || m_opr.top() == '-' || m_opr.top() == '*' || m_opr.top() == '/') { double b = m_num.top(); m_num.pop(); double a = m_num.top(); m_num.pop(); switch (op) { case '+': m_num.push(a + b); break; case '-': m_num.push(a - b); break; case '*': m_num.push(a * b); break; case '/': if (b == 0) throw runtime_error("Division by zero"); m_num.push(a / b); break; } } else { double c = m_num.top(); m_num.pop(); switch (op) { case '^': m_num.push(c * c); break; case '√': if (c < 0) throw runtime_error("Square root of negative number"); m_num.push(sqrt(c)); break; case 'L': if (c <= 0) throw runtime_error("Logarithm of non-positive number"); m_num.push(log(c)); break; case '1': if (c == 0) throw runtime_error("Division by zero"); m_num.push(1.0 / c); break; } } } double Calculator::doit(const string& exp) { m_num.clean(); for (auto it = exp.begin(); it != exp.end();) { if (isNum(it)) m_num.push(readNum(it)); else { //单目运算符 char op = *it; if (op == '^' && (it + 1) != exp.end() && *(it + 1) == '2') { op = '^'; ++it; } else if (op == '1' && (it + 1) != exp.end() && *(it + 1) == '/' && (it + 2) != exp.end() && *(it + 2) == 'x') { op = '1'; it += 2; } else if (op == 'L' && (it + 1) != exp.end() && *(it + 1) == 'n') { op = 'L'; ++it; } // 括号 if (op == '(') { m_opr.push(op); ++it; continue; } else if (op == ')') { while (m_opr.top() != '(') { if (m_opr.top() == '#') { throw runtime_error("Mismatched parentheses"); } calculate(); } m_opr.pop(); // 弹出左括号 ++it; continue; } while (precedence(*it) <= precedence(m_opr.top())) { if (m_opr.top() == '#') break; calculate(); } if (*it != '=') m_opr.push (*it); ++it; //为啥 继续扫描要放在这里 } } while (m_opr.top() != '#') { if (m_opr.top() == '(') { throw runtime_error("Mismatched parentheses"); } calculate(); } return m_num.top(); } 分析为何无法实现2*(2+2)的计算,以及单目运算符的完成情况
最新发布
05-18
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值