Daniel Aarno
bishop@kth.se
Programsystemkonstruktion med C++
Övning 3
Översikt övning 3
Virtuellt arv Strömmar Iteratorer
Effektiv C++
Tips
Tentatal
2
Virtuellt arv
3
Undvik att få dubbla medlemmar vid multipelt arv
class Animal {
private:
string name;
};
class Donkey : virtual public Animal {
};
class Horse : virtual public Animal {
};
class Mule : public Donkey, public Horse {
private:
// inherits one name from Animal
};
Strömmar
4
Input/Output i C
int fprintf(FILE *stream, const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int main() { char c;
FILE* fp = fopen(“/tmp/file.txt/”, “rb”);
while(fscanf(fp, “%c”, &c) == 1) printf(“%c”, c);
fclose(fp);
fprintf(stderr, “Nothing more in the file”);
fprintf(stdout, “Pi has the value: %.4f %s”, M_PI, “\nSo there!\n”);
printf(“Press enter to exit:> “);
fflush(stdout);
scanf(“%*s”); //< Read a string and ignore it return 0;
}
Strömmar (cont'd)
5
Input/Output i C++
int main() { char c;
istream infile(“/tmp/file.txt/”, ios_base::binary);
while(infile.get(c)) { //< can not use infile >> c
cout << c; // because it ignores binary mode }
cerr << “Nothing more in the file”;
cout << “Pi has the value: “ << precision(4) <<
M_PI << “\nSo there!” << endl;
cout << “Press enter to exit:> “;
cout.flush();
cin.ignore(); //< Read a string and ignore it return 0;
} //infile closed here
Strömmar (cont'd)
6
Formatering
width(int i);
precision(int i);
setf(fmtflags f);
fmtflags flags();
fmtflags:
left //< pad after value right //< pad before value
boolalpha //< symbolic representation of true/false scientific //< 3.141592e3
fixed //< 3141.592 ...
Strömmar (cont'd)
7
class A { public:
int i;
virtual ~A();
virtual void doStuff();
};
class B : public A { public:
int j;
void doStuff();
};
ostream& operator<<(ostream &o, const A &a) { o << a.i;
return o;
}
ostream& operator<<(ostream &o, const B &b) { o << b.i << ' ' << b.j;
return o;
}
Strömmar (cont'd)
8
int main() {
A a;
B b;
A &aRef = b; //< OK, a is public base of B cout << a << endl;
cout << b << endl;
cout << aRef << endl; //< Hmmm, what will happen here?
return 0;
}
Strömmar (cont'd)
9
class A { public:
int i;
virtual ~A();
virtual void doStuff();
virtual ostream& print(ostream &o) { o << i; return o;}
};
class B : public A { public:
int j;
void doStuff();
ostream& print(ostream &o) { o << i << j; return o; } };
ostream& operator<<(ostream &o, const A &a) {
return a.print(o); //< Now all subclasses of A will print //correctly. using only one operator<<
//and virtual bindings in the class }
Iteratorer
10
template<typename T>
ostream& operator<<(ostream& os, const vector<T> &v) {
string sep = "";
ofstream *ofs = dynamic_cast<ofstream*>(&os);
if(ofs != 0) { os << v.size();
sep = " ";
}
for(typename vector<T>::const_iterator it = v.begin();
it != v.end(); ++it) { os << sep << *it;
sep = " ";
}
return os;
}
Iteratorer (cont'd)
11
template<typename T>
istream& operator>>(istream& is, vector<T> &outVec) {
ifstream *ifs = dynamic_cast<ifstream*>(&is);
if(ifs != 0)
return ReadVec(*ifs, outVec);
string line;
getline(is, line);
outVec.clear();
istringstream iss(line);
T val;
while(iss >> val) {
outVec.push_back(val);
}
return is;
}
Iteratorer (cont'd)
12
template<typename T>
istream& ReadVec(ifstream& is, vector<T> &outVec) {
int nmemb;
is >> nmemb;
outVec.clear();
istream_iterator<T> isi(is);
copy(isi, istream_iterator<T>(), back_inserter(outVec));
return is;
}
Iteratorer (cont'd)
13
template<typename T>
ostream& operator<<(ostream& os, const vector<T> &v) {
ofstream *ofs = dynamic_cast<ofstream*>(&os);
if(ofs != 0) {
os << v.size() << ' ';
}
copy(v.begin(), v.end(), ostream_iterator<T>(os, " "));
return os;
}
Effektiv C++
14
Undvik temporära objekt
Använd initialiseringslista Undvik return-by-value
Var noggrann med iteratorer
Använd std-funktioner, algoritmer etc
Optimera där det hjäper
Effektiv C++ (cont'd)
15
Template <typename T> void foo(U &a, U &b) { cout << “foo()” << endl;
}
Template <typename T> void bar(const U &a, const U &b) { cout << “bar()” << endl;
}
int main () { int i = 2;
char c = 'a';
foo<int>(i,c); //< will not compile because temporary //< objects may not be changed
bar<int>(i,c); //< compiles OK }
Temporära objekt
Effektiv C++ (cont'd)
16
struct Student { string name;
string addr;
};
string FindAddr(list<Student> l, string name { for(list<Student>::iterator i = l.begin();
i != l.end(); i++) {
if(*i == name)
return i>addr;
}
return “”;
}
Temporära objekt
Finn 5 “fel”
struct Student { string name;
string addr;
};
string FindAddr(list<Student> l, string name) { for(list<Student>::iterator i = l.begin();
i != l.end(); i++) {
if(*i == name)
return i>addr;
}
return “”;
}
Effektiv C++ (cont'd)
17 Temporära objekt
Ej const&
++i är snabbare
i->name
Effektiv C++ (cont'd)
18
struct Student { string name;
string addr;
};
const string& FindAddr(const list<Student> &l, const string &name
{
static const string dummy;
for(list<Student>::const_iterator i = l.begin();
i != l.end(); ++i) {
if(i>name == name) return i>addr;
}
return dummy;
}
Temporära objekt
Effektiv C++ (cont'd)
19
class NameEq {
const string &m_name;
public:
NameEq(const std::string &nam) : m_name(nam) {}
bool operator()(const Student& s) { return s.name == m_name; }
};
const string& FindAddr(const list<Student> &l, const string &name
{
static const string dummy;
list<Student>::const_iterator it =
find_if(l.begin(), l.end(), NameEq(name));
return it != l.end() ? *it : dummy;
}