[C++]初识

Posted jiangwei0512

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[C++]初识相关的知识,希望对你有一定的参考价值。

说明

关于C++的内容,都是在已经了解了C语言的基础之上总结的,所以有不少C++的基础,因为也是C语言的基础,所以不会特意说明。

输入输出

首先是一个简单的例子:

#include <iostream>

int main()
{
    int v1 = 0, v2 = 0;

    std::cout << "Enter two numbers:" << std::endl;
    std::cin >> v1 >> v2;
    std::cout << "The sum of " << v1 << " and " << v2 << " is " << v1 + v2 << std::endl;

    return 0;
}

cout是标准输出,cin是标准输入,此外还有cerr是标准错误,clog是标准日志记录,对应的头文件:

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  /**
   *  @name Standard Stream Objects
   *
   *  The &lt;iostream&gt; header declares the eight <em>standard stream
   *  objects</em>.  For other declarations, see
   *  http://gcc.gnu.org/onlinedocs/libstdc++/manual/io.html
   *  and the @link iosfwd I/O forward declarations @endlink
   *
   *  They are required by default to cooperate with the global C
   *  library's @c FILE streams, and to be available during program
   *  startup and termination. For more information, see the section of the
   *  manual linked to above.
  */
  //@{
  extern istream cin;		/// Linked to standard input
  extern ostream cout;		/// Linked to standard output
  extern ostream cerr;		/// Linked to standard error (unbuffered)
  extern ostream clog;		/// Linked to standard error (buffered)

#ifdef _GLIBCXX_USE_WCHAR_T
  extern wistream wcin;		/// Linked to standard input
  extern wostream wcout;	/// Linked to standard output
  extern wostream wcerr;	/// Linked to standard error (unbuffered)
  extern wostream wclog;	/// Linked to standard error (buffered)
#endif
  //@}

  // For construction of filebuffers for cout, cin, cerr, clog et. al.
  static ios_base::Init __ioinit;

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace

可以看到在cout、cin之前加了std,它是命名空间的名称,使用它是为了防止全局命名的冲突,这样写当然比较麻烦,如果一直使用的都是std这个命名空间,就可以直接在开头导入:

using namespace std;

还有一个endl,它是一个操纵符,写入endl的效果是结束当前行,并将与设备关联的缓冲区中的内容刷写到设备中,而不是仅停留在内存。

<<和>>是输出运算符和输入运算符。<<接收两个运算对象,左边是ostream对象,右边是需要输出的值。<<运算符的返回值是左边的ostream对象,这样才可以像代码中那样连续多次使用<<。>>也类似,接收两个对象,左侧是istream对象,右侧是一个普通对象来接收读入的数据,并返回左侧的istream对象。

代码执行的结果:

F:\\Codes\\cppprimer>IoStream.exe
Enter two numbers:
1 2
The sum of 1 and 2 is 3

F:\\Codes\\cppprimer>IoStream.exe
Enter two numbers:
1 2a
The sum of 1 and 2 is 3

F:\\Codes\\cppprimer>IoStream.exe
Enter two numbers:
a b
The sum of 0 and 0 is 0

从上面的程序中其实是可以看到一些可疑的点的,这个涉及更复杂的内容,将在后续进一步介绍。

控制流

这里只介绍与C语言有差异的。

首先是for:

int main()
{
    for (int i = 0; i < 10; i++)
    {
        cout << i << endl;
    }

    return 0;
}

主要的区别在于i这个变量,C++中可以直接放到for循环语句中;C语言中其实也可以这么用,但是似乎有版本限制,且一般也不这么用。这里还需要注意i只在for循环对应的代码块中才有效,在其外是无效的。

其次是结合输入的控制流:

int main()
{
    int sum = 0;
    int value;
    
    while (cin >> value)
    {
        sum += value;
    }
    cout << "The sum is: " << sum << endl;
    
    return 0;
}

执行结果:

F:\\Codes\\cppprimer>Control.exe
1 2 3
^Z
The sum is: 6 

这里的while循环会一直持续,直到按下Ctrl+z再加Enter为止,这表示了输入的结束,然后执行后续的打印结果。这里是while的例子,cin也可以用在if中:

int main()
{
    int value;

    if (cin >> value)
    {
        cout << "The input: " << value << endl;
    }

    return 0;
}

这里只获取第一个输入,然后打印值,结果如下:

F:\\Codes\\cppprimer>Control.exe
1
The input: 1   

C语言当也可以通过scanf完成类似的写法

类简介

类用来定义自己的数据结构及关联的操作。下面是一个例子:

class Sales_item {
    // these declarations are explained section 7.2.1, p. 270
    // and in chapter 14, pages 557, 558, 561
    friend std::istream& operator>>(std::istream&, Sales_item&);
    friend std::ostream& operator<<(std::ostream&, const Sales_item&);
    friend bool operator<(const Sales_item&, const Sales_item&);
    friend bool operator==(const Sales_item&, const Sales_item&);

public:
    // constructors are explained in section 7.1.4, pages 262 - 265
    // default constructor needed to initialize members of built-in type
    Sales_item() = default;
    Sales_item(const std::string &book): bookNo(book) { }
    Sales_item(std::istream &is) { is >> *this; }

public:
    // operations on Sales_item objects
    // member binary operator: left-hand operand bound to implicit this pointer
    Sales_item& operator+=(const Sales_item&);
    // operations on Sales_item objects
    std::string isbn() const { return bookNo; }
    double avg_price() const;

// private members as before
private:
    std::string bookNo;      // implicitly initialized to the empty string
    unsigned units_sold = 0; // explicitly initialized
    double revenue = 0.0;
};

几点说明:

  1. 类使用class关键字定义;

  2. >>,<<(这两个在这里指的是输入输出运算符,不是位运算符),<和==这些基本运算符被重载(Override)了,但是因为它们其实不是当前类拥有的接口,所以不能直接放到类里面,需要作friend声明。

  3. public声明类公开的接口,private声明类的私有数据;

  4. 第一个public下是构造函数;

  5. 第二个public下是普通的公开接口;

这里有几个问题需要解决。

一是为什么需要将==等运算符Override?原因很简单,因为对于Sales_item这个自定义的数据类型,两个类对象是无法比较的,如下面的代码:

int main()
{
    Sales_item item1, item2;
    
    if (item1 == item2)
        std::cout << "==" << std::endl;
    else
        std::cout << "!=" << std::endl;
    
    return 0;
}

编译时直接报错:

F:\\Codes\\cppprimer\\1\\add_item.cc: In function 'int main()':
F:\\Codes\\cppprimer\\1\\add_item.cc:37:15: error: no match for 'operator==' (operand types are 'Sales_item' and 'Sales_item')
     if (item1 == item2)

可以看到直接提示没有匹配的operator==。

二是Override的时候为什么还要将operator==设置为友元,这主要就得看它的实现:

inline bool
operator==(const Sales_item &lhs, const Sales_item &rhs)
{
    // must be made a friend of Sales_item
    return lhs.units_sold == rhs.units_sold &&
        lhs.revenue == rhs.revenue &&
        lhs.isbn() == rhs.isbn();
}

从代码可以看到,只有当Sales_item中的units_sold、revenue和isbn()函数的返回值都相等,才表示两个Sales_item对象相等。但是问题在于units_sold和revenue是私有变量,operator==是不能直接访问的。为了访问能够成功,在定义Sales_item的时候就需要显式地声明operator==为友元。这也是为什么operator!=不需要声明为友元的缘故,如下所示:

inline bool
operator!=(const Sales_item &lhs, const Sales_item &rhs)
{
    return !(lhs == rhs); // != defined in terms of operator==
}

在operator!=的实现中不需要访问Sales_item的私有数据,也就不需要声明为友元了。

三是为什么operator+=却被定义成了Sales_item的公共接口,还有一个operator+放在了Sales_item定义之外:

// nonmember binary operator: must declare a parameter for each operand
// assumes that both objects refer to the same ISBN
Sales_item
operator+(const Sales_item& lhs, const Sales_item& rhs)
{
    Sales_item ret(lhs);  // copy (|lhs|) into a local object that we'll return
    ret += rhs;           // add in the contents of (|rhs|)
    return ret;           // return (|ret|) by value
}

关于这个问题,目前没有找到答案。似乎可以是成员变量、也可以不是成员变量。

此外还有很多的知识点,比如构造函数、引用等,后面深入的时候再说明。

以上是关于[C++]初识的主要内容,如果未能解决你的问题,请参考以下文章

Java初识方法

这些 C++ 代码片段有啥作用?

有趣的 C++ 代码片段,有啥解释吗? [复制]

以下代码片段 C++ 的说明

C++ 代码片段执行

此 Canon SDK C++ 代码片段的等效 C# 代码是啥?