1.类定义输入运算符 >> 时候,代码最后应该检测 输入流是否为有效,如果无效,应该把输入对象置于默认初始化状态。
定义>>时候,类必须是非常量引用。定义<<,最好是常量引用。
定义的时候不能加friend.
2.关于日期输入的正确格式:
Date & Date::operator=(const string &date)
{
istringstream is(date);
char ch1,ch2;
is >> year >> ch1 >> month >> ch2 >> day;
if(!is || ch1 != '-' || ch2 != '-' )
throw invalid_argument("Bad date");
if(month < 1 || month > 12 || day < 1 || day > 21)
throw invalid_argument("Bad date");
return *this;
}
3.
#include <string>
#include <iostream>
using namespace std;
class Test
{
int &fun()const
{
return a;
}
private:
int a;
};
int main()
{
Test t1;
return 0;
}
binding reference of type ‘int&’ to ‘const int’ discards qualifiers
const成员函数不能返回类成员的非常量引用。因为有修改类成员的风险。
3.
g++报错"undefined reference to `vtable for XXX' "的原因
原因就一个:没有全部实现XXX基类的纯虚函数.
4.
// items定义成一个multiset,可以将同一本书的多条交易信息保存到一个multiset中,
// 这里不能用圆括号,因为default member initializer来初始化成员有2
// 个方法,list initialization,即一对花括号.第二种是copy initializa//tion,即 等号.如果尝试用圆括号,编译器会误以为是函数声明,所以/报告compare is not a type..
multiset<shared_ptr<Quote>,decltype(compare)*> items{compare};
所以这里给items初始化有不能使用圆括号。
5.
MoveBase_cmd_vel_sub = node_handle.subscribe( "/movebase_cmd_vel", 60, DHRobotBase::moveBase_cmd_vel); // 订阅 topic
在使用这句话时出现这个问题:
error: invalid use of non-static member function "/movebase_cmd_vel", 60, DHRobotBase::moveBase_cmd_vel);
折腾了好久终于弄好了:
MoveBase_cmd_vel_sub = node_handle.subscribe("/movebase_cmd_vel", 60, &DHRobotBase::moveBase_cmd_vel,this); // 订阅topic
原因大概是这个:在C++语言中,对于一个由类名加俩冒号再加成员名构成的东西(学名叫“quilified-id”),比如:A::x,只有当x是A类的静态成员的时候,A::x才能表示一个左值。而对于函数类型到函数指针类型的默认转换,只有当函数类型是左值的时候才行
6.关于c、c++的输入输出函数的掌握:
/***********************************************************************************这个读取字符的函数可以把所有的输入字符都归结为' '和非' '两类,减轻输入字符后的处理难度。
*/
char read_char(void)
{
int ch = getchar();
if(ch == '\t' || ch == '\n')
return ' ';
return ch;
}
读入单词的一个经典程序,c现代方法上的
/*******************************************************************************
len表示读入的单词的长度,word是字符指针
*******************************************************************************/
void read_word(char * word,int len)
{
int ch,pos = 0;
while((ch = read_char()) == ' ') //调用read_char()函数比getchar()更方便
;
while(ch != ' ' && ch != EOF) //EOF是文件结束符,表示linux中CTRL+D或者 win中ctrl+z
{
if(pos < len)
word[pos ++] = ch;
ch = read_char(); //如果这里读入”空格“或者EOF,那么读入停止
}
word[pos] = '\0'; //末尾添加\0
}
自己的c语言太菜了,真是无地自容了。
7.
//本程序只有一个主题:
//对于代码中的某个节点来说,基类的公有成员是否是可访问的,则派生类向基类的转换也是可访问的;反之则不行。
//我自己的语言理解这句话是:对于某个用户来说,如果这个用户能透过派生类看到(或者使用)基类的公有成员,那么这个用户就可以使用从派生类向基类的转换;反之,则不行。
//如果上面的难理解,那我就这样说:某个用户能否使用派生类对象向基类对象的转换,关键是看对这个用户来说,能否通过派生类对象使用基类的共有成员,B b;b.pub_men//(如果能这样使用就对,不能就错);
#include <string>
#include <iostream>
using namespace std;
class A
{
public:
int a= 1;
protected:
int b = 2;
private:
int c = 3;
};
class B:protected A
{
public:
void f()const
{
A * a;
B * b = new B;
//下面的这句,能否实现,关键在于这个用户能否通过派生类看到基类的共有成员。
//下面这句的用户其实就是派生类本身(A是基类,B是派生类),肯定能看见基类的共有成员了
//所以下面的语句是合法的
a = b; //派生类对象到基类对象的转换
cout << "B::b" << b->b << endl;
delete b;
}
};
class C:protected B
{
public:
void f(){cout << "A::b" <<b << endl;}
};
int main()
{
A * a = new A;
B * b = new B;
//下面这个语句 c=b 是否合理,关键是这个语句的用户能否透过派生类(B类)看见基类(A类)的共有成员,
//答案是否定的,因为B:protected A,这句话说明了,A类的共有成员在B类中成为了protected成员。
//对于普通用户而言,B类protected成员是不可见的。所以下面这句代码汇报错。
//A * c = b; //使用了派生类对象向基类对象的转换
b->f();
delete a;
delete b;
return 0;
}
8.自己在做15.9的课后习题15.41时候,把OrQuery的eval求并集的set_intersection的函数中,前两个迭代器,本应该是shared_ptr<set<line_no>>的迭代器,结果带入shared_ptr<vector<string>>的迭代器,结果出现如下看不懂的错误:
a.out query.cc quote.h textquery.cc
r@r:~/coml/c++/15/15.9/ex/15.41$ g++ main.cc query.cc -o 123
In file included from /usr/include/c++/9/algorithm:62,
from query.h:38,
from query.cc:7:
/usr/include/c++/9/bits/stl_algo.h: In instantiation of ‘_OutputIterator std::__set_intersection(_InputIterator1, _InputIterator1, _InputIterator2, _InputIterator2, _OutputIterator, _Compare) [with _InputIterator1 = __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _InputIterator2 = __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _OutputIterator = std::insert_iterator<std::set<long unsigned int> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]’:
/usr/include/c++/9/bits/stl_algo.h:5307:48: required from ‘_OIter std::set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter) [with _IIter1 = __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _IIter2 = __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _OIter = std::insert_iterator<std::set<long unsigned int> >]’
query.h:425:93: required from here
/usr/include/c++/9/bits/stl_algo.h:5258:16: error: no match for ‘operator=’ (operand types are ‘std::insert_iterator<std::set<long unsigned int> >’ and ‘std::__cxx11::basic_string<char>’)
5258 | *__result = *__first1;
| ~~~~~~~~~~^~~~~~~~~~~
In file included from /usr/include/c++/9/bits/stl_algobase.h:67,
from /usr/include/c++/9/bits/char_traits.h:39,
from /usr/include/c++/9/string:40,
from query.cc:1:
/usr/include/c++/9/bits/stl_iterator.h:716:7: note: candidate: ‘std::insert_iterator<_Container>& std::insert_iterator<_Container>::operator=(const typename _Container::value_type&) [with _Container = std::set<long unsigned int>; typename _Container::value_type = long unsigned int]’
716 | operator=(const typename _Container::value_type& __value)
| ^~~~~~~~
/usr/include/c++/9/bits/stl_iterator.h:716:56: note: no known conversion for argument 1 from ‘std::__cxx11::basic_string<char>’ to ‘const value_type&’ {aka ‘const long unsigned int&’}
716 | operator=(const typename _Container::value_type& __value)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
/usr/include/c++/9/bits/stl_iterator.h:724:7: note: candidate: ‘std::insert_iterator<_Container>& std::insert_iterator<_Container>::operator=(typename _Container::value_type&&) [with _Container = std::set<long unsigned int>; typename _Container::value_type = long unsigned int]’
724 | operator=(typename _Container::value_type&& __value)
| ^~~~~~~~
/usr/include/c++/9/bits/stl_iterator.h:724:51: note: no known conversion for argument 1 from ‘std::__cxx11::basic_string<char>’ to ‘std::set<long unsigned int>::value_type&&’ {aka ‘long unsigned int&&’}
724 | operator=(typename _Container::value_type&& __value)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
/usr/include/c++/9/bits/stl_iterator.h:665:11: note: candidate: ‘constexpr std::insert_iterator<std::set<long unsigned int> >& std::insert_iterator<std::set<long unsigned int> >::operator=(const std::insert_iterator<std::set<long unsigned int> >&)’
665 | class insert_iterator
| ^~~~~~~~~~~~~~~
/usr/include/c++/9/bits/stl_iterator.h:665:11: note: no known conversion for argument 1 from ‘std::__cxx11::basic_string<char>’ to ‘const std::insert_iterator<std::set<long unsigned int> >&’
/usr/include/c++/9/bits/stl_iterator.h:665:11: note: candidate: ‘constexpr std::insert_iterator<std::set<long unsigned int> >& std::insert_iterator<std::set<long unsigned int> >::operator=(std::insert_iterator<std::set<long unsigned int> >&&)’
/usr/include/c++/9/bits/stl_iterator.h:665:11: note: no known conversion for argument 1 from ‘std::__cxx11::basic_string<char>’ to ‘std::insert_iterator<std::set<long unsigned int> >&&’
9.
//vec.h
#ifndef VEC_H
#define VEC_H
#include <string>
#include <iostream>
#include <memory>
#include <algorithm>
using namespace std;
template<typename T>
class Vec{
public:
Vec();
Vec(const Vec<T> & );
Vec& operator=(const Vec &);
Vec& operator=(Vec &&);
~Vec(){free();}
size_t size()const{return first_free - elements;}
void push_back(const T&);
T* begin()const;
T* end()const;
T& front();
T& back();
const T& front()const;
const T& back()const;
size_t capacity()const;
private:
static allocator<T> alloc;
void reallocate();
pair<T*,T*>
alloc_n_copy(T*,T*);//根据一对指针分配等量的存储空间,并返回首尾指针
void chk_n_alloc(){if(first_free == cap) reallocate();}
void free();
T * elements;
T * first_free;
T * cap;
};
/*
template<typename T>
typename
Vec<T>::allocator<T> alloc;*/
template<typename T>
Vec<T>::Vec():elements(nullptr),first_free(nullptr),cap(nullptr){}
template<typename T>
Vec<T>::Vec(const Vec<T> &t)
{
auto data = alloc_n_copy(t.begin(),t.end());
elements = data.frist;
first_free = cap = data.second;
}
template<typename T>
Vec<T>& Vec<T>::operator=(const Vec<T> & t)
{
auto data = alloc_n_copy(t.begin(),t.end());
free();
elements = data.frist;
first_free = cap = data.second;
return *this;
}
template<typename T>
void Vec<T>::reallocate()
{
auto capacity = size()? 2*size() : 1;
auto new_elements = alloc.allocate(capacity);
auto new_first_free = uninitialized_copy(elements,first_free,new_elements);
free();
elements = new_elements;
first_free = new_first_free;
cap = elements + capacity;
}
template<typename T>
T* Vec<T>::begin()const
{
return elements;
}
template<typename T>
T* Vec<T>::end()const
{
return first_free;
}
template<typename T>
size_t Vec<T>::capacity()const
{
return cap - elements;
}
template<typename T>
void Vec<T>::free()
{
if(elements)
{
for(T* ptr = first_free; ptr != elements;)
{
alloc.destroy(-- ptr);
}
alloc.deallocate(elements,cap - elements);
elements = first_free = cap = nullptr;
}
}
/*
template<typename T>
template<typename T>
template<typename T>
template<typename T>
template<typename T>
template<typename T>
template<typename T>
template<typename T>
*/
#endif
//1.cc
#include <string>
#include <iostream>
#include <memory>
#include "vec.h"
using namespace std;
int main()
{
Vec<string> v;
/*
cout << v.size() << endl;
cout << v.capacity() << endl;
*/
return 0;
}
编译如下:
/usr/bin/ld: /tmp/ccqjCquG.o: in function `Vec<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::free()':
1.cc:(.text._ZN3VecINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE4freeEv[_ZN3VecINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE4freeEv]+0x48): undefined reference to `Vec<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::alloc'
/usr/bin/ld: 1.cc:(.text._ZN3VecINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE4freeEv[_ZN3VecINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE4freeEv]+0x7c): undefined reference to `Vec<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::alloc'
collect2: error: ld returned 1 exit status
18章习题18.1
18章的习题18.1的最后一个补充问题:如果将b中的throw语句改为throw p,会发生什么?我自己自己理解是,catch语句块可能和不再p指向的对象的作用域范围内,如果抛出一个指针,那么等到找到(可能在外层的try语句中或者调用函数的外层函数中的)匹配的catch语句后,原来的异常对象早就被销毁了,所以应该是报错才对,看下面我自己编程验证的结果。
#include <string>
#include <iostream>
#include <stdexcept>
using namespace std;
void fun(int k)
{
try{
cout << "try block 1:" << endl;
try{
if(k == 0)
{
range_error r("range error,hahhaha");
exception *p = &r;
throw p;
}
}
catch (range_error * ptr){ cout << "call range_error *ptr" << ptr -> what() << endl;}
catch (exception e){ cout << "exception e" << e.what() <<endl;}
cout << " this is block1's statement." << endl;
}
//到这里才能知道到匹配的catch子句,原来的p指向的对象在这里不该已经被销毁了吗?
//怎么还能正常运行呢?
catch (exception *p){ cout << "try block2 :exception *p " << p->what() << endl;}
cout << "this is block2 's final statement." << endl;
}
int main()
{
fun(0);
cout << "this is main function's final statement.\n" << endl;
return 0;
}
运行结果显示,能正常处理异常?为何?
try block 1:
try block2 :exception *p range error,hahhaha
this is block2 's final statement.
this is main function's final statement.
下面是是一个c语言的问题,关于qsort的使用的,请看:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int compareString(const void* p,const void *q)
{
return strcmp((char*)p,(char*)q);
}
int main()
{
char *p1 = "abcasdf";
char *p2 = "acafdda";
char *p3 = "basdf";
char *p4 = "xasdfasdf";
char *p5 = "kjilasdf";
char *p6 = "xabasdf";
char * arr[] = {p2,p3,p5,p1,p4,p6};
size_t sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr,sz,sizeof(char *),compareString);
int i;
for(i = 0;i != sizeof(arr) / sizeof(arr[0]) ; ++ i)
{
printf("%s\n",arr[i]);
}
printf("result:%d",strcmp(p5,p4));
return 0;
}
为什么排序结果如下(不是应该按照字典排序吗?下面根本就是错误的):
abcasdf
acafdda
basdf
xasdfasdf
kjilasdf
xabasdf