C++学习笔记

来源:互联网 发布:知君本无邪by尼罗txt 编辑:程序博客网 时间:2024/06/14 13:28
类声明
class XXX;
只能以有限的方式使用已经被声明但没有定义的类类型,不能定义该类类型的对象。
但是可以声明指向该类类型的指针或者引用

inline成员函数
4种方式
1.直接写在类定义中
2.在类定义中,函数声明的前面加inline
3.类体外,定义函数加inline
4.声明和定义中都加inline

const类对象和成员函数(volatile类似)
const类对象只能访问const成员函数
const成员函数必须在声明和定义中都加const
const成员函数不能修改数据成员,但可以修改指针所指的对象
const类对象可以调用非const构造函数和析构函数,对象在构造完成

时刻到析构开始时刻,被认为是const

mutable(易变的)数据成员
将一个数据成员声明为mutable,const成员函数可以修改它

this指针
1.返回对象本身
Screen &Screen::clear()
{
    .....
    return *this;   
}
2.copy对象判断
void Screen::copy(Screen &other)
{
    if(this == &other)
        return;
    ......   
}

静态数据成员
1.不占据对象的空间
2.在类定义之外初始化
#include "acct.h"
double Acct::_interestRate = 0.001;
......
//account.h
class Account
{
.......
private:
    static const int nameSize = 16;//int类型是特殊情况,可以在类体内初始化
    //nameSize已经变为常量表达式
    static const char name[nameSize];//不能初始化    
}
//account.cpp
const int nameSize; //必须的成员定义
const char name[nameSize] = "Savings Account";

3.静态数据成员的类型可以是其所属的类
class Bar
{
private:
    static Bar b1; //ok
    Bar b2;//错误
    Bar *b3, &b4;//ok   
};
4.静态数据成员可以作为类成员函数的缺省实参
extern int var;
class Foo {
private:
    int var;
    static int stvar;//
public:
    int func1(int arg = var); //错误
    int func2(int arg = stvar); //ok
    int func3(int arg = ::var); //ok
};

静态成员函数

1.不能声明为const和volatile
2.出现在类体外的函数定义不能指定关键字static
3.不能访问非静态成员

使用前自增一般效率会更高些

命名空间namespace
namespace xx
{
    int i;
    int j =i;
}
namespace xx //可以递增
{
    int k = i;
}

#include <iostream>
namespace xx {
    void foo(int) { std::cout << "int case\n"; }
}

using namespace xx; //using指令
namespace xx {
    void foo(double) { std::cout << "double case\n"; }
}
int main(int argc, char *argv[])
{
    foo(1.3); //输出 "double case"

    system("PAUSE");
    return 0;
}

#include <iostream>
namespace xx {
    void foo(int) { std::cout << "int case\n"; }
}
using xx::foo; //using声明
namespace xx {
    void foo(double) { std::cout << "double case\n"; }
}
int main(int argc, char *argv[])

{
    foo(1.3);//输出 "int case"

    system("PAUSE");
    return 0;
}

名字空间别名
namespace x = xx;

从标准输入读取字符
int ch;
ch = cin.get();
string line;
getline(cin, line); //读取一行

cerr输出不缓冲
clog输出带缓冲

void get_str(string &str);

get_str("haha"); //错误,字符串字面量不是string对象

void get_str(const string &str);
get_str("haha"); //OK

行为的分类
1.完全定义的行为:C++标准定义的行为,sizeof(char) = 1;
2.实现定义的行为: 编译器定义,int的大小,char是有符号数还是无符号数
3.未指定的行为:求值顺序 函数调用顺序
4.未定义的行为:数组越界

函数模板
1.当函数模板和普通函数都匹配时,优先考虑普通函数
2.函数模板可以重载,注意std中的函数模板,使用全局模板,::max(...)
3.特化函数模板:模板参数为空,函数名字后面提供显式参数
template<>
string const max<string const &>(string const &first, string const &second) {}

explicit 用于构造函数,它禁止编译器将构造函数参数用作从参数的类型到类类型的隐式转换
数据成员按照类定义中声明他们的顺序被初始化,而与初始化列表中的顺序无关
在类定义中初始化数据成员的三个条件:1.static成员;2.整形成员;3.const成员

而且要在类的实现文件中,定义:int const XXX::xx;

将copy构造函数和operator=函数声明为私有的,防止复制
class A
{
public:
    A() {}
    virtual ~A() {}
private:
    A(A const &);
    A & operator=(A const &);
};
int main()
{
    A a1;
    A a2(a1); //错误,A(A const &)为私有函数
    A a3 = a1; //错误,A(A const &)为私有函数,注意调用的函数
    A a4;
    a4 = a1; //错误,A & operator=(A const &)为私有函数
}

如果已经修改了容器,则之前声明的迭代器将不能再使用了!
vector<int> v(1);
v[0] = 100;
vector<int>::iterator it = v.begin();
cout << *it << endl;
v.push_back(200);
cout << *it << endl; //危险

任何含有vitual成员函数和公有析构函数的类,将析构函数声明为virtual

匿名命名空间只在文件作用域可见,类似于C的static
namespace
{
    int i = 0;
    ......
   
}
void foo()
{
    cout << i << endl; // 0
  

写文件
<fstream> <ostream>
string filename;
cin >> filename;
ofstream outfile(filename.c_str());
//ofstream outfile("test.txt", ios::app); //追加

if(outfile)
{
    outfile << "hello" << 2 * 3 << endl;
    outfile.close();
}
else
{
    cout << "Fail to open file\n";
}

读文件
ifstream infile;
infile.open("test.txt");

if(infile)
{
    string line;
    getline(infile, line);
    infile.close();
}
else
{
    cout << "Open error\n";
}
字符串流<sstream>
stringstream ss;
ss << "hello\n";
ss << 5*3 << ".\n";
cout << ss.str();

string str("1 2 3");
stringsteam ss(str);
int val;
for(int i=0; i!=3; ++i)
{

 ss >> val;
    cout << val << '\n';
}

操作符重载
class A
{
    A();
    ~A();
   
    istream &get_from(istream &in) //输入
    {
        in >> a;
        in >> b;
        return in;
    }
    ostream &send_to(ostream &out) //输出
    {
        out << a;
        out << b;
        return out;
    }
    A & operator*=(A const &r)
    {
        a *= r.a;
        b *= r.b;
        return *this;
    }
    operator double() //转换
    {
        return double(a)/b;
    }
private:
    A(double); //禁止由double到A的转换
private:
    int a;
    int b;
};
inline istream & operator>>(istream &in, A &a) //输入
{
    return a.get_from(in);
}
inline ostream & operator<<(ostream &out, A const &a) //输出
{
    return a.send_to(out);
}
inline A operator*(A lhs, A const & rhs) //乘法
{
    return lhs *= rhs;
}
从文本中读取单词
string get_word(istream &in)
{
    string word;
    while(true)
    {
        char const letter = in.get();
        if(in.eof()) return word;
        if(isalpha(letter))
        {
            word += letter;
            break;
        }
    }
    while(true)
    {
        char const letter = in.get();
        if(in.eof()) break;
        if(not isalpha(letter)) break;
        word += letter;
    }
    return word;
}
void read_file(string filename)
{
    ifstream file(filename.c_str());
    set<string> words;
    while(true)
    {
        string const word = get_word(file);
        words.insert(word);
        if(file.eof()) break;
    }
}
统计单词出现的次数
void stats_word()
{
    map<string, int> words;
    while(true)
    {
        string const word = get_word(in);
        ++words[word];
        if(in.eof()) break;
    }
    for(map<string, int>::iterator it = words.begin(); it != words.end(); ++it)
        cout << it->first << it->second << endl;
}
不能对关联容器进行排序
按照单词出现的频率排序
vector<pair<string, int> > seq_words(words.begin(), words.end());
stable_sort(seq_words.begin(), seq_words.end(), compare);
inline bool compare(pair<string, int> const &lhs, pair<string, int> const &rhs)
{
    return lhs.second > rhs.second;
}
创建字典
aeg -->age, gea...
typedef multimap<string, string> dict;
typedef multimap<string, string>::const_iterator cit;
void make_anagram_dict(dict &anagrams, ifstream &source)
{
    while(true)
    {
        string word;
        source >> word;
        if(source.eof()) return;
        if(not isalpha(word[0])) return;
        string letters = word;
        sort(letters.begin(), letters.end());
        anagrams.insert(make_pair(letters, word));
    }
}
void find_anagram(dict const &anagrams, string const &word, ostream & out=cout)
{
    string letters = word;
    sort(letters.begin(), letters.end());
    cit lower = anagrams.lower_bound(letters);
    cit upper = anagrams.upper_bound(letters);
    if(lower = upper)
    {
        cout << "No word found\n";
        return;
    }
    for(cit it=lower; it!=upper; ++it)
        cout << it->second << endl;
   
    return;
}

0 0
原创粉丝点击