Category Archives: c c++

QT 学习笔记

  1. The Q_OBJECT macro at the beginning of the class definition is necessary for all classes that define signals or slots.
  2. Classes that use the Q_OBJECT macro must have moc run on them. This isn’t a problem because qmake automatically adds the necessary rules to the makefile. But if you forget to regenerate your makefile using qmake and moc isn’t run, the linker will complain that some functions are declared but not implemented.

c++ 学习笔记

  • 1. Never Return a Pointer to a Local Object
  • 2. Function Declarations Go in Header Files

It may be temptingand would be legalto put a function declaration directly in each source file that uses the function. The problem with this approach is that it is tedious and error-prone. By putting function declarations into header files, we can ensure that all the declarations for a given function agree. If the interface to the function changes, only one declaration must be changed.

  • 3. Constraints on Specifying Default Arguments

Specify default argument(s) in either the function definition or declaration. However, a parameter can have its default argument specified only once in a file. Default arguments ordinarily should be specified with the declaration for the function and placed in an appropriate header

  • 4. Unlike other function definitions, inlines should be defined in header files.
  • 5. Functions cannot be overloaded based only on differences in the return type.
  • 6. It is a bad idea to declare a function locally. Function declarations should go in header files.

If we declare a function locally, that function hides rather than overloads the same function declared in an outer scope. As a consequence, declarations for every version of an overloaded function must appear in the same scope.

void print(const string &);
void print(double);   // overloads the print function
void fooBar(int ival)
{
  void print(int);   // new scope: hides previous instances of print
  print("Value: ");  // error: print(const string &) is hidden
  print(ival); // ok: print(int) is visible
  print(3.14); // ok: calls print(int); print(double) is hidden
}

  • 7. No Copy or Assign for IO Objects
  • cannot have a vector (or other container) that holds stream objects.
  • cannot have a parameter or return type that is one of the stream types. If we need to pass or return an IO object, it must be passed or returned as a pointer or reference:
  • 8. IO => Buffers Are Not Flushed if the Program Crashes

Flushing the Output Buffer

cout << "hi!" << flush;      // flushes the buffer; adds no data
cout << "hi!" << ends;       // inserts a null, then flushes the buffer
cout << "hi!" << endl;       // inserts a newline, then flushes the buffer
  • 9. When we copy one container into another, the types must match exactly: The container type and element type must be the same.
  • 10. Containers of Containers
vector< vector<string> > lines; // ok: space required between close >
vector< vector<string>> lines; // error: >> treated as shift operator

  • 11. >, >=, <, <= Supported only for vector and deque‘s iterator.

The reason that only vector and deque support the relational operators is that only vector and deque offer fast, random access to their elements. These containers are guaranteed to let us efficiently jump directly to an element given its position in the container. Because these containers support random access by position, it is possible for their iterators to efficiently implement the arithmetic and relational operations.

  • 12. Container Elements Are Copies

When we add an element to a container, we do so by copying the element value into the container. Similarly, when we initialize a container by providing a range of elements, the new container contains copies of the original range of elements. There is no relationship between the element in the container and the value from which it was copied. Subsequent changes to the element in the container have no effect on the value that was copied, and vice versa.

  • 13. we can think of a constructor as executing in two phases: (1) the initialization phase and (2) a general computation phase
         Sales_item::Sales_item(const string &book)
    
         {
    
             isbn = book;
    
             units_sold = 0;
    
             revenue = 0.0;
    
         }

    This constructor assigns, but does not explicitly initialize, the members of class Sales_item. Regardless of the lack of an explicit initializer, the isbn member is initialized before the constructor is executed. This constructor implicitly uses the default string constructor to initialize isbn. When the body of the constructor is executed, the isbn member already has a value. That value is overwritten by the assignment inside the constructor body.

    • 14. 不能在类声明中初始化const数据成员。以下用法是错误的,因为类的对象未被创建时,编译器不知道SIZE的值是什么。

    class A

    {

        const int SIZE = 100;     // 错误,企图在类声明中初始化const数据成员

        int array[SIZE];              // 错误,未知的SIZE

    };

    const数据成员的初始化只能在类构造函数的初始化表中进行,例如

    class A

    {

        A(int size);      // 构造函数

        const int SIZE ;

    };

    A::A(int size) : SIZE(size)    // 构造函数的初始化表

    {

        …

    }

    A  a(100); // 对象 a 的SIZE值为100

    A  b(200); // 对象 b 的SIZE值为200

    怎样才能建立在整个类中都恒定的常量呢?别指望const数据成员了,应该用类中的枚举常量来实现。例如

    class A

    {…

        enum { SIZE1 = 100, SIZE2 = 200}; // 枚举常量

        int array1[SIZE1]; 
        int array2[SIZE2];

        };

    枚举常量不会占用对象的存储空间,它们在编译时被全部求值。枚举常量的缺点是:它的隐含数据类型是整数,其最大值有限,且不能表示浮点数(如PI=3.14159)。

    const Objects Are Local to a File By Default

    When we define a nonconst variable at global scope, it is accessible throughout the program. We can define a nonconst variable in one file andassuming an appropriate declaration has been madecan use that variable in another file:

          // file_1.cc
          int counter;  // definition
          // file_2.cc
          extern int counter; // uses counter from file_1
          ++counter;          // increments counter defined in file_1

    Unlike other variables, unless otherwise specified, const variables declared at global scope are local to the file in which the object is defined. The variable exists in that file only and cannot be accessed by other files.

    We can make a const object accessible throughout the program by specifying that it is extern:

          // file_1.cc
          // defines and initializes a const that is accessible to other files
          extern const int bufSize = fcn();
          // file_2.cc
          extern const int bufSize; // uses bufSize from file_1
          // uses bufSize defined in file_1
          for (int index = 0; index != bufSize; ++index)
                // ...

    In this program, file_1.cc defines and initializes bufSize to the result returned from calling the function named fcn. The definition of bufSize is extern, meaning that bufSize can be used in other files. The declaration in file_2.cc is also made extern. In this case, the extern signifies that bufSize is a declaration and hence no initializer is provided.

    c/c++写cgi之helloworld

    最近比较闲,所以又回头来学习下c/c++, 但看来看去也没什么好学的,没什么项目,光学一门语言确实没什么好看的,那就来用c/c++写个cgi来玩玩吧,之前没做过cgi,所以这样就既可了解cgi又可复习c/c++了。

    先来个c/c++的cgi hello world吧,本人是在apache下运行的啊

    新建文件hello.c

    #include <stdio.h>
    main() {
        printf("Content-type:text/html\n\n");
        printf("Hello,World!");
    }

    用命令$gcc –o hello hello.c 生成 hello

    然后查看apache配置文件httpd.conf, 设置为:[默认的差不多就是这样]

    ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
    <Directory "/var/www/cgi-bin">
        AllowOverride All
        Options ExecCGI
        Order allow,deny
        Allow from all
    </Directory>

    然后把生成的hello复制到 /var/www/cgi-bin/下,如果修改了配置的话,就先重起apache, 这时输入http://localhost/cgi-bin/hello,就应该可以看到结果了

    make_pair

    关于make_pair(1, “Test”)为什么有错:

    1 先声明一些东西:
    template <typename T1, typename T2>
    struct pair
    {
    T1 first;
    T2 second;
    // …
    };

    template <typename T1, typename T2>
    pair<T1, T2> make_pair(T1 const&, T2 const&);

    2 当调用make_pair(1, “Test”)时

    2.1 类型推导
    #1 T1 = int;
    #2 由于”Test”的类型是char const[5],
    而且函数参数T2 const&是引用,
    所以T2 = char const[5]
    2.2 实例化函数
    pair<int, char const[5]> make_pair<>(int const&, char const (const&)[5]);

    3 实例化pair<int, char const[5]>类型导致:

    struct pair<>
    {
    int first;
    char const second[5];
    //…
    };
    这个类型根本就不可能用来生成对象,因为你
    无法初始化常数数组成员。

    4 实例化失败导致编译错误:
    template <typename T1, typename T2>
    pair<T1, T2> make_pair(T1 const& t1, T2 const& t2)
    {
    return pair<T1, T2>(t1, t2); // 无法构造pair对象,见上面3的描述
    ^^^^^^^^^^^^^^^^^^^^^
    }