void* operator new(size_t size) { if (void* mem = malloc(size)) return mem; else throw std::bad_alloc(); } void operator delete(void* mem)noexcept { free(mem); }
inline void* StrVec::operator new(size_t size) { if (void* mem = malloc(size)) return mem; else throw std::bad_alloc(); } inline void StrVec::operator delete(void* mem) noexcept { std::free(mem); }
(b)失败,基类指针要转化为派生类指针,基类指针需指向派生类;
(c)失败,A *pa = new D具有二义性,A是D的一个二义基类。
A *pa = new C; try{ const C &c = dynamic_cast<const C&>(*pa); }catch(std::bad_cast &e){ std::cout << e.what() << std::endl; }
我们想使用基类对象的指针或引用执行某个派生类操作并且该操作不是虚函数时可以使用RTTI运算符
int main(int argc, char const* argv[]) { chapter15::Query_base* pb1 = new chapter15::AndQuery(chapter15::Query("value1"), chapter15::Query("value2")); chapter15::Query_base* pb2 = new chapter15::OrQuery(chapter15::Query("value1"), chapter15::Query("value2")); if (chapter15::AndQuery* aq = dynamic_cast<chapter15::AndQuery*>(pb1)) { cout << "aq成功"; } else { cout << "aq失败"; } if (chapter15::OrQuery* oq = dynamic_cast<chapter15::OrQuery*>(pb2)) { cout << "oq成功"; } else { cout << "oq失败"; } return 0; }
int main(int argc, char const* argv[]) { chapter15::Query_base* pb1 = new chapter15::AndQuery(chapter15::Query("value1"), chapter15::Query("value2")); chapter15::Query_base* pb2 = new chapter15::OrQuery(chapter15::Query("value1"), chapter15::Query("value2")); try { chapter15::AndQuery& aq = dynamic_cast<chapter15::AndQuery&>(*pb1); cout << "aq成功"; } catch(std::bad_cast) { cout << "aq失败"; } try { chapter15::OrQuery& aq = dynamic_cast<chapter15::OrQuery&>(*pb2); cout << "oq成功"; } catch (std::bad_cast) { cout << "oq失败"; } return 0; }
int main(int argc, char const* argv[]) { chapter15::Query_base* pb1 = new chapter15::AndQuery(chapter15::Query("value1"), chapter15::Query("value2")); chapter15::Query_base* pb2 = new chapter15::OrQuery(chapter15::Query("value1"), chapter15::Query("value2")); if (typeid(*pb1) == typeid(*pb2)) { cout << "pb1和pb2指向同一种类型" << endl; if (typeid(*pb1) == typeid(chapter15::AndQuery)) cout << "这种类型是AndQuery" << endl; else cout << "这种类型不是AndQuery" << endl; } else cout << "pb1和pb2不指向同一种类型" << endl; return 0; }
class Base { friend bool operator==(const Base&, const Base&); public: Base() = default; Base(int i_) : i(i_) { } protected: virtual bool equal(const Base&) const; private: int i; }; class Derived : public Base { public: Derived() = default; Derived(std::string s_, int i_) : s(s_), Base(i_) { } protected: bool equal(const Base&) const; private: std::string s; }; bool operator==(const Base& lhs, const Base& rhs) { return typeid(lhs) == typeid(rhs) && lhs.equal(rhs); } bool Base::equal(const Base& rhs) const { return this->i == rhs.i; } bool Derived::equal(const Base& rhs) const { auto r = dynamic_cast<const Derived&>(rhs); return (this->s == r.s) && this->Base::equal(rhs); } int main(int argc, char const* argv[]) { int arr[10]; Derived d; Base* p = &d; std::cout << typeid(42).name() << ", " << typeid(arr).name() << ", " << typeid(Sales_data).name() << ", " << typeid(std::string).name() << ", " << typeid(p).name() << ", " << typeid(*p).name() << std::endl; }
int, int [10], class Derived, class Sales_data, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >, class Base *, class Derived
(a)class A *
(b)class A *
(c)class B
普通的数据指针指向一个对象;类成员指针指向类的非静态成员。当初始化这样一个指针时,我们令其指向类的某个成员,但是不指定该成员所属的对象;直到使用成员指针时,才提供所属的对象。
static const pos Screen::* pcursor() { return &Screen::cursor; }
static const string Sales_data::* pbookNo() { return &Sales_data::bookNo; }
合法,传入参数和返回类型都相同
普通函数指针和指向成员函数的指针区别在于不存在自动转换规则
using Action = double(Sales_data::*)()const;
template<pos X, pos Y> class Screen { public: friend class Window_mgr; friend std::istream& operator>>(std::istream& is, Screen<X, Y>& s){ char a; is >> a; std::string temp(X* Y, a); s.contents = temp; return is; } friend std::ostream& operator<<(std::ostream& os, Screen<X, Y>& s){ unsigned int i, j; for (i = 0; i < s.height; i++) { os << s.contents.substr(0, X) << std::endl; } return os; } //Screen(pos ht,pos wd):height(ht),width(wd),contents(ht*wd,‘ ‘){} using Action = Screen<X, Y>&(Screen<X, Y>::*)(char); using Action = Screen<X, Y>&(Screen<X, Y>::*)(pos, pos, char); using Action = Screen<X, Y>& (Screen<X, Y>::*)(pos, pos); using Action = Screen<X, Y>& (Screen<X, Y>::*)(std::ostream& os)const; Screen<X, Y>(char c=‘ ‘) :height(X), width(Y), contents(height* width, c) {} static const pos Screen::* pcursor() { return &Screen::cursor; } static const std::string Screen::* data() { return &Screen::contents; } Screen<X, Y>& set(char); Screen<X, Y>& set(pos, pos,char); Screen<X, Y>& move(pos, pos); Screen<X, Y> display(std::ostream& os); const Screen<X, Y> display(std::ostream& os)const; pos size() const; private: pos cursor = 0; pos height = 0, width = 0; std::string contents; void do_display(std::ostream& os)const { os << contents; } };
int main(int argc, char* argv[]) { vector<string>vec_str{"","",""}; cout<<std::count_if(vec_str.begin(), vec_str.end(), std::mem_fn(&string::empty)); }
int main(int argc, char* argv[]) { vector<Sales_data>vec_str; Sales_data record; double fee; cin >> fee; while (cin >> record) { vec_str.push_back(record); } auto f = std::mem_fn(&Sales_data::avg_price); std::find_if(vec_str.begin(), vec_str.end(),[&](Sales_data& s) {return f(s)>fee; }); }
#include <fstream> using std::ifstream; using std::ofstream; #include <iostream> using std::cin; using std::cout; using std::endl; #include <map> using std::map; using std::multimap; #include <set> using std::multiset; using std::set; #include <sstream> using std::istringstream; #include <string> using std::string; #include <unordered_map> using std::unordered_map; #include <vector> #include "StrVec.h" #include <algorithm> using std::vector; #ifndef TEXTQUERT_H_ #define TEXTQUERT_H_ #include "DebugDelete.h" namespace chapter10 { class TextQuery { friend class QueryResult; public: class QueryResult; TextQuery() :text(new StrVec, DebugDelete("TextQuery::StrVec")), query_words(new map<string, std::shared_ptr<set<size_t>>>, DebugDelete("TextQuery::map<string, std::shared_ptr<set<size_t>>>")) {} TextQuery(ifstream& ifs); QueryResult query(string s) const; ~TextQuery(); private: std::shared_ptr <StrVec> text; std::shared_ptr<map<string, std::shared_ptr<set<size_t>>>> query_words; }; class TextQuery::QueryResult { public: friend std::ostream& print(std::ostream& os, const QueryResult qr); using QueryIterator = set<size_t>::iterator; public: QueryResult(string& w, std::shared_ptr<set<size_t>> n, std::shared_ptr<StrVec> i) :word(w), nos(new set<size_t>, DebugDelete("QueryResult::set<size_t>")), inputs(new StrVec, DebugDelete("QueryResult::StrVec")) { nos = n; inputs = i; } ~QueryResult(); QueryIterator begin() { return nos->begin(); } QueryIterator end() { return nos->end(); } std::shared_ptr <StrVec> get_file() { return inputs; } private: string word; std::shared_ptr<set<size_t>> nos; std::shared_ptr<StrVec> inputs; }; TextQuery::QueryResult::~QueryResult() { } inline TextQuery::TextQuery(ifstream& ifs) : text(new StrVec, DebugDelete("TextQuery::StrVec")), query_words(new map<string, std::shared_ptr<set<size_t>>>, DebugDelete("TextQuery::map<string, std::shared_ptr<set<size_t>>>")) { size_t size = 0; if (ifs) { for (string line; getline(ifs, line, ‘.‘); ++size) { text->push_back(line); istringstream iss(line); size = text->size(); for (string text, word; iss >> text; word.clear()) { std::remove_copy_if(text.begin(), text.end(), std::back_inserter(word), ispunct); // use reference avoid count of shared_ptr add. auto& nos = (*query_words)[word]; if (!nos) nos.reset(new std::set<size_t>); nos->insert(size); } } } } inline TextQuery::QueryResult TextQuery::query(string s) const { static std::shared_ptr<std::set<size_t>> nodate(new std::set<size_t>, DebugDelete("TextQuery::std::set<size_t>")); auto found = query_words->find(s); if (found == query_words->end()) { cout << s + " is not in the text" << endl; return QueryResult(s, nodate, text); } else return QueryResult(s, found->second, text); } TextQuery::~TextQuery() { } std::ostream& print(std::ostream& os, const TextQuery::QueryResult qr) { os << qr.word << " occurs " << qr.nos->size() << " times" << endl; for (auto i : *qr.nos) { os << "\t(line " << i + 1 << ") " << qr.inputs->at(i) << std::endl; } return os; } } #endif // !TEXTQUERT_H_
#include <string> #ifndef _TOKEN_H_ #define _TOKEN_H_ class Token { public: Token():tok(INT),ival(0){} Token(const Token& t) :tok(t.tok) { copyUnion(t); } Token& operator=(const Token&); ~Token() { if (tok == STR)sval.~basic_string(); } Token& operator=(const std::string&); Token& operator=(char); Token& operator=(int); Token& operator=(double); private: enum { INT, CHAR, DBL, STR }tok; union { char cval; int ival; double dval; std::string sval; }; void copyUnion(const Token&); }; inline Token& Token::operator=(const Token&t) { if (tok == STR && t.tok != STR)sval.~basic_string(); if (tok == STR && t.tok == STR) sval = t.sval; else { copyUnion(t); } tok = t.tok; return*this; } inline Token& Token::operator=(const std::string&s) { if (tok == STR)sval = s; else new (&sval)std::string(s); tok = STR; return*this; } inline Token& Token::operator=(char c) { if (tok == STR)sval.~basic_string(); cval = c; tok = CHAR; return*this; } inline Token& Token::operator=(int i) { if (tok == STR)sval.~basic_string(); ival = i; tok = INT; return*this; } inline Token& Token::operator=(double d) { if (tok == STR)sval.~basic_string(); dval = d; tok = DBL; return*this; } inline void Token::copyUnion(const Token&t) { switch (t.tok) { case Token::INT:ival = t.ival; break; case Token::CHAR:cval = t.cval; break; case Token::DBL:dval = t.dval; break; case Token::STR: new(&sval)std::string(t.sval); break; } } #endif // !_TOKEN_H_
#include <string> #include"Sales_data.h" #ifndef _TOKEN_H_ #define _TOKEN_H_ class Token { public: Token():tok(INT),ival(0){} Token(const Token& t) :tok(t.tok) { copyUnion(t); } Token& operator=(const Token&); ~Token() { if (tok == STR)sval.~basic_string(); } Token& operator=(const std::string&); Token& operator=(const Sales_data&); Token& operator=(char); Token& operator=(int); Token& operator=(double); private: enum { INT, CHAR, DBL, STR,SDATA }tok; union { char cval; int ival; double dval; std::string sval; Sales_data sdval; }; void copyUnion(const Token&); }; inline Token& Token::operator=(const Token&t) { if (tok == STR && t.tok != STR)sval.~basic_string(); if (tok == SDATA && t.tok != SDATA)sdval.~Sales_data(); if (tok == STR && t.tok == STR) sval = t.sval; else if (tok == SDATA && t.tok == SDATA) sdval = t.sdval; else { copyUnion(t); } tok = t.tok; return*this; } inline Token& Token::operator=(const std::string&s) { if (tok == SDATA)sdval.~Sales_data(); if (tok == STR)sval = s; else new (&sval)std::string(s); tok = STR; return*this; } inline Token& Token::operator=(const Sales_data& s_data) { if (tok == STR)sval.~basic_string(); if (tok == SDATA)sdval = s_data; else new (&sdval)Sales_data(s_data); tok = SDATA; return*this; } inline Token& Token::operator=(char c) { if (tok == STR)sval.~basic_string(); if (tok == SDATA)sdval.~Sales_data(); cval = c; tok = CHAR; return*this; } inline Token& Token::operator=(int i) { if (tok == STR)sval.~basic_string(); if (tok == SDATA)sdval.~Sales_data(); ival = i; tok = INT; return*this; } inline Token& Token::operator=(double d) { if (tok == STR)sval.~basic_string(); if (tok == SDATA)sdval.~Sales_data(); dval = d; tok = DBL; return*this; } inline void Token::copyUnion(const Token&t) { switch (t.tok) { case Token::INT:ival = t.ival; break; case Token::CHAR:cval = t.cval; break; case Token::DBL:dval = t.dval; break; case Token::STR: new(&sval)std::string(t.sval); break; case Token::SDATA: new(&sdval)Sales_data(t.sdval); break; } } #endif // !_TOKEN_H_
#include <string> #include"Sales_data.h" #ifndef _TOKEN_H_ #define _TOKEN_H_ class Token { public: Token():tok(INT),ival(0){} Token(const Token& t) :tok(t.tok) { copyUnion(t); } Token& operator=(const Token&); Token(Token&& t) :tok(std::move(t.tok)) { moveUnion(std::move(t)); } Token& operator=(Token&&); ~Token() { if (tok == STR)sval.~basic_string(); } Token& operator=(const std::string&); Token& operator=(const Sales_data&); Token& operator=(char); Token& operator=(int); Token& operator=(double); private: enum { INT, CHAR, DBL, STR,SDATA }tok; union { char cval; int ival; double dval; std::string sval; Sales_data sdval; }; void copyUnion(const Token&); void moveUnion(const Token&&); void free() { if (tok == STR) sval.std::string::~string(); if (tok == SDATA) sdval.~Sales_data(); } }; inline Token& Token::operator=(const Token&t) { if (tok == STR && t.tok != STR)sval.std::string::~string(); if (tok == SDATA && t.tok != SDATA)sdval.~Sales_data(); if (tok == STR && t.tok == STR) sval = t.sval; else if (tok == SDATA && t.tok == SDATA) sdval = t.sdval; else { copyUnion(t); } tok = t.tok; return*this; } inline Token& Token::operator=(Token&& t) { if (this != &t) { free(); moveUnion(std::move(t)); std::move(t.tok); } return *this; } inline Token& Token::operator=(const std::string&s) { if (tok == SDATA)sdval.~Sales_data(); if (tok == STR)sval = s; else new (&sval)std::string(s); tok = STR; return*this; } inline Token& Token::operator=(const Sales_data& s_data) { if (tok == STR)sval.~basic_string(); if (tok == SDATA)sdval = s_data; else new (&sdval)Sales_data(s_data); tok = SDATA; return*this; } inline Token& Token::operator=(char c) { free(); cval = c; tok = CHAR; return*this; } inline Token& Token::operator=(int i) { free(); ival = i; tok = INT; return*this; } inline Token& Token::operator=(double d) { free(); dval = d; tok = DBL; return*this; } inline void Token::copyUnion(const Token&t) { switch (t.tok) { case Token::INT:ival = t.ival; break; case Token::CHAR:cval = t.cval; break; case Token::DBL:dval = t.dval; break; case Token::STR: new(&sval)std::string(t.sval); break; case Token::SDATA: new(&sdval)Sales_data(t.sdval); break; } } inline void Token::moveUnion(const Token&& t) { switch (t.tok) { case Token::INT:ival = t.ival; break; case Token::CHAR:cval = t.cval; break; case Token::DBL:dval = t.dval; break; case Token::STR: new(&sval)std::string(std::move(t.sval)); break; case Token::SDATA: new(&sdval)Sales_data(std::move(t.sdval)); break; } } #endif // !_TOKEN_H_
如果是拷贝赋值,则看是否是类类型,则直接赋值,如果是移动赋值则跳过
int main(int argc, char* argv[]) { string s = "string"; Sales_data item("c++ primer 5", 12, 128.0); int i = 12; char c = ‘c‘; double d = 1.28; Token t,t1; t = i; cout << t << "\t"; t1 = t; cout << t1 << "\t"; t = d; cout << t << "\t"; t = s; cout << t << "\t"; t = item; cout << t << endl; Token t2 = t; cout << t2 << "\t"; t2 = s; cout << t2 << "\t"; t2 = t; cout << t2 << "\t"; t2 = c; cout << t2 << "\t"; t = s; t2 = std::move(t); cout << t2 << endl; Token t3 = std::move(t2); cout << t3 << "\t"; t3 = t3; cout << t3 << "\t"; t3 = item; cout << t3 << endl; t2 = std::move(t3); cout << t2 << endl; }
不合法,C语言不支持函数重载
原文:https://www.cnblogs.com/GodZhuan/p/14141819.html