[笔记]C++笔记(4)

CH13 Templates
Function templates
template <typename T1, typename T2, ...> // Note, use typename and class are equivalent unless you are dealing with template template parameters (use typename) 
// template function here

The function with actual types is called a function template instance.

Templates Class

classname<typename> class

Explicit instantiation for class templates (to prevent from linking error in instantiating classes)

// The template class definition goes in the header. The template class member functions goes in the code file
// Ensure the full Array template definition can be seen
#include "Array.h"
#include "Array.cpp" // we're breaking best practices here, but only in this one place
 
// #include other .h and .cpp template definitions you need here
// Instantiate ALL classes you need
template class Array<int>; // Explicitly instantiate template Array<int>
template class Array<double>; // Explicitly instantiate template Array<double>
 
// instantiate other templates here
// finally, include this cpp in project
Expression parameters

A template expression parameter can be

  • A value that has an integral type or enumeration
  • A pointer or reference to a class object/ function/ class member function

The expression serves as a stencil -- it replaces placeholders during compilation. There is no dynamic allocation.

Function/class template specialization

Can be used to define specific function for specified type.

template <> // outside of the template class
void Storage<double>::print() // redefine class member function for type double
{
    std::cout << std::scientific << m_value << '\n';
}

Functions do not support partial specialization as of C++14(Only full specialization is permitted, i.e.,explicitly specify all types):

template<typename T, typename U> void f() {}   //allowed!
template<> void f<int, char>()            {}   //allowed!
template<typename T> void f<char, T>()    {}   //not allowed!
template<typename T> void f<T, int>()     {}   //not allowed!

Class however support partial specialization,

Using partial template class specialization to create separate pointer and non-pointer implementations of a class is extremely useful when you want a class to handle both differently, but in a way that’s completely transparent to the end-user.


CH14 Exceptions

The catch-all handler

int main()
{
	try
	{
		something
	}
	catch(type) // Handle a specific exception type
	{
		something
	}
	catch(..) // The catch-all handler ensures no uncaught exception is passed to OS.
	{
		something
	}
}

Exceptions can be wrapped in a class, but you should use a reference to do that: catch (user_defined_exception& ex) It can prevent from expensive copying a class. Catching exceptions by pointer should generally be avoided unless you have a specific reason to do so.

A useful trick: put most derived class first to prevent from class slicing

#include <stdexcept>

catch ( std::bad_alloc &ex) // Assuming a bad_alloc is thrown, std::bad_alloc is inherited from std::exception
    {
        cerr << "caught std::bad_alloc";
    }
    catch (std::exception &ex) // If you put this first, the exception will be handled by this block because of object slicing
    {
        cerr << "caught std::exception";
    }
 

The exceptions have a what() function printing error message, but this string is meant to be used for descriptive text only.

catch (std::exception &exception)
{
    std::cerr << "Standard exception: " << exception.what() << '\n'; // Assuming std::runtime_error (or something other) is thrown
}

Derive your exception from std::exception:

#include <exception> // for std::exception
 
class ArrayException: public std::exception
{
private:
	std::string m_error;
 
public:
	ArrayException(std::string error)
		: m_error(error)
	{
	}
 
	 const char* what() { return m_error.c_str(); } // return the std::string as a const C-style string
};

When rethrowing the same exception, use the throw keyword by itself. i.e., throw;

Function try blocks:

class B : public A
{
public:
	B(int x) try : A(x) // note addition of try keyword here
	{
	}
	catch (...) // note this is at same level of indentation as the function itself
	{
                // Exceptions from member initializer list or constructor body of A are caught here
                std::cerr << "Construction of A failed\n";
                // If an exception isn't explicitly thrown here, the current exception will be implicitly rethrown
	}
};

Notes on exception:

  • Remember to clean up resources after exceptions are thrown
  • Exceptions should never be thrown in destructors
  • Performance issue: exception handling is best used for truly exceptional cases and catastrophic errors, not for routine error handling.
CH15 Move sematics and smart pointers

To be cont'd

CH16 An intro to STL
Containers
  • Sequence container: std::vector, std::deque, std::array, std::list, std::forward_list, and std::basic_string
  • Associative container: std::set, std::multiset, std::map, std::multimap
    • compare elements using operator<
  • Container adapeters: std::stack, std::queue, std::priority_queue
Iterators

Iterators are container member functions.

  • Overloaded operators:
    • *: deference
    • ++/--: moving forward/backward
    • !=/==: comparison
    • =: moving to position
  • Positions:
    • begin()/end()
    • cbegin()/cend() -> for const (read-only) iterators
  • Type
    • container::iterator read/write iterator
    • container::const_iterator: read only iterator
Algorithms

Algorithms are implemented as global functions that operate using iterators. This means that each algorithm only needs to be implemented once, and it will generally automatically work for all containers that provides a set of iterators (including your custom container classes).

CH17 std::string

Note: A C-style string is simply an array of characters that uses a null terminator. It has many downsides and is generally not suggested. (e.g. = is not overloaded so comparing two C-style string is comparing two pointers.)

<cstring>: C++ version of <string.h>, dealing with C-style string. Use <string> instead.

namespace std
{
    typedef basic_string<char> string; // For utf8 characters
    typedef basic_string<wchar_t> wstring; // For utf16 characters
}

Details see http://www.learncpp.com/cpp-tutorial/17-1-stdstring-and-stdwstring/

CH18 I/O

iostream

iostream
  • istream: >> extraction from input stream;
  • ostream: << insertion to output stream.
  • iostream: combined above.

<iomanip.h>: manipulate stream.

Manipulator example:

cin>>setw(m)>>buff; // read only m-1 (1 for \0) characters from buff
cout<<endl; output '\n' and flush buffer (write everything in buffer to device)

Extraction and whitespace:

char ch;
cin.get(ch); // whitespace will be accepted. Note, get DOES NOT READ \n
char buff[100];
cin.getline(buff,50); // this also extracts \n

More functions:

  • ignore() discards the first character in the stream.
  • ignore(int nCount) discards the first nCount characters.
  • peek() allows you to read a character from the stream without removing it from the stream.
  • unget() returns the last character read back into the stream so it can be read again by the next call.
  • putback(char ch) allows you to put a character of your choice back into the stream to be read by the next call.

Formatting:

cout.setf(ios::showpos | ios::uppercase); // turn on the ios::showpos and ios::uppercase flag, use unsetf to set off flags. Note, uppercase doesn't apply to lower case letters, it only applies to numbers ->see language specification

// a case on mutually exclusive flag:
cout.unsetf(ios::dec); // turn off decimal output FIRST
cout.setf(ios::hex); // turn on hexadecimal output
cout << 27 << endl;

//or instead
// Turn on ios::hex as the only ios::basefield flag
cout.setf(ios::hex, ios::basefield);
cout << 27 << endl;

// you can use ios::fmtflags to store flag status
http://www.cplusplus.com/reference/ios/ios_base/fmtflags/

More manipulators see web.

String buffer: stringstream in <sstream>

Stream status:

ios::goodbit, ios::badbit (fatal error), ios::eofbit, ios::failbit (non-fatal error). They also have member function counterparts, namely, bool ios::good() , etc. (return true if everything is good)

File I/O

ifstream, ofstream and fstream are included in fstream.h.

ifstream returns 0 when reaches EOF. A typical reading process:

  // ifstream is used for reading files
    // We'll read from a file called Sample.dat
    ifstream inf("Sample.dat");
 
    // If we couldn't open the input file stream for reading
    if (!inf)
    {
        // Print an error and exit
        cerr << "Uh oh, Sample.dat could not be opened for reading!" << endl;
        exit(1);
    }
 
    // While there's still stuff left to read
    while (inf)
    {
        // read stuff from the file into a string and print it
        std::string strInput;
        getline(inf, strInput);
        cout << strInput << endl;
    }

endl flushes buffer (as ostream::flush() does), so use \n instead for performance concerns.

ofstream outf("Sample.dat", ios::app);

Append Meaning
app Opens the file in append mode
ate Seeks to the end of the file before reading/writing
binary Opens the file in binary mode (instead of text mode)
in Opens the file in read mode (default for ifstream)
nocreate Opens the file only if it already exists
noreplace Opens the file only if it does not already exist
out Opens the file in write mode (default for ofstream)
trunc Erases the file if it already exists

Random file access using seekp() and seekg() (seek get and seek put):

seekp/seekg(int byteoffset, ios_flag)

Ios seek flag Meaning
beg The offset is relative to the beginning of the file (default)
cur The offset is relative to the current location of the file pointer
end The offset is relative to the end of the file

Do not write addresses to files. The variables that were originally at those addresses may be at different addresses when you read their values back in from disk, and the addresses will be invalid.

Static library: .a(archive) in Linux or .lib in Windows

Dynamic (shared) library: .so(shared object) in Linux or .dll in Windows

Something more...
  1. __cplusplus is predefined macro for C++ compilers.

    static_assert(__cplusplus > 199711L, "Program requires C++11 capable compiler");
    // static_assert also requires C++11
    

posted on 2017-03-06 10:16  小硕鼠  阅读(178)  评论(0)    收藏  举报

导航