`
lobin
  • 浏览: 417506 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论
阅读更多

 

写道

 

写道

 

写道

 

 

写道
C++: Windows编程: 第二章 Visual C++下的MFC编程
https://www.iteye.com/blog/lobin-2508615

 

 

C++继承了C的风格。

C with Class

C程序基本上可以不用修改就可以移植到C++程序中

C++也可以采用C中的编程风格。

 

C++支持面向对象

C++支持模板编程

C++支持元编程

C++还支持函数式编程

 

写道
Welcome to Bjarne Stroustrup's homepage!
https://www.stroustrup.com

 

C

 

C++

从C到C++

 

写道
C++ reference
https://en.cppreference.com/w/

 

写道
Standard C++ Library reference
https://cplusplus.com/reference/

 

 

 

类型

 

literal type

字面类型可以是void、标量类型、引用类型、数组字面类型、或者满足以下所有性质的class类型:

 

-它有一个简单的析构函数

-它是一个聚合类型或至少有一个不是复制或移动构造的构造函数或构造函数模板,并且

-其所有的非静态数据成员和基类都是non-volatile(非易失性)的文字类型。

 

 

 

 

 

表达式

 

拷贝

 

 

结构体

C++中结构体和C中的结构体还是有本质区别的,基本上已经具备了C++类型的特征。结构体不只可以有成员变量,还可以有成员函数,这个成员函数说的不是C结构体中的函数指针,这本质上还是成员变量,当然C++也可以有函数指针。

 

C++的结构体支持成员函数。

 

在结构体的成员函数中可以通过this来获取结构体对象,这在函数指针成员中也是可以的。这在C结构体中是没有的。

 

可以说,C++中的结构体除了继承方式以及成员访问默认都是public之外(C++中的结构体成员也无法指定是public、protected或者private),其他的基本和C++的类是一样的。

 

C++中的结构体和联合体定义为“a class defined with the keywords struct or union”,这和类定义为“a class defined with the keyword class”并没有多大差异。

 

trivially copyable class

 

 

trivial class

写道
A trivial class is a class that has a trivial default constructor (12.1) and is trivially copyable.

意思就是trivial class是一个有trivial默认构造函数的类,并且是一个trivially copyable class。

写道
[ Note: In particular, a trivially copyable or trivial class does not have virtual functions or virtual base
classes.— end note ]

 

 

POD struct

 

写道
A POD struct is a class that is both a trivial class and a standard-layout class, and has no non-static
data members of type non-POD struct, non-POD union (or array of such types).

 

意思就是一个POD结构体是一个扁平的类以及标准布局的类,没有非POD结构体以及非POD联合体(包括这种类型的数组)的非静态数据成员。

 

POD union

 

写道
Similarly, a POD union
is a union that is both a trivial class and a standard layout class, and has no non-static data members of
type non-POD struct, non-POD union (or array of such types).

 

意思和上面的一样,就是一个POD联合体是一个扁平的类以及标准布局的类,没有非POD结构体以及非POD联合体(包括这种类型的数组)的非静态数据成员。

 

POD union和POD struct并没有什么区别。

 

POD class

 

写道
A POD class is a class that is either a POD struct or a POD union.

意思就是一个POD类是一个POD struct或者POD union。

 

如果我们按照C中的结构体或者联合体来理解POD类的话,POD类感觉和类(class)没什么关系。

 

 

移动

 

写道
◆ move()
template<typename _Tp >
constexpr std::remove_reference<_Tp>::type&& std::move ( _Tp && __t )
constexprnoexcept
Convert a value to an rvalue.

Parameters
__t A thing of arbitrary type.
Returns
The parameter cast to an rvalue-reference to allow moving it.
Definition at line 104 of file move.h.

https://gcc.gnu.org/onlinedocs/gcc-12.1.0/libstdc++/api/a01588.html#ga9f81219bfbfaac50d44f79095a639620

move函数其实是将一个值转换为右值(引用)。

 

参考c++/v1/type_traits中的代码:

template <class _Tp> 
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
typename remove_reference<_Tp>::type&&
move(_Tp&& __t) _NOEXCEPT
{
    typedef typename remove_reference<_Tp>::type _Up; 
    return static_cast<_Up&&>(__t);
}

下面是展开后的代码:

template <class _Tp>
inline __attribute__ ((__visibility__("hidden"), __always_inline__)) constexpr
typename remove_reference<_Tp>::type&&
move(_Tp&& __t) noexcept
{
    typedef typename remove_reference<_Tp>::type _Up;
    return static_cast<_Up&&>(__t);
}

remove_reference定义如下:

template <class _Tp> struct _LIBCPP_TYPE_VIS_ONLY remove_reference        {typedef _Tp type;};
template <class _Tp> struct _LIBCPP_TYPE_VIS_ONLY remove_reference<_Tp&>  {typedef _Tp type;};
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
template <class _Tp> struct _LIBCPP_TYPE_VIS_ONLY remove_reference<_Tp&&> {typedef _Tp type;};
#endif

 

 

  int i = 100;

  int &&i2 = std::move(i);

 

写道
move_if_noexcept()
template<typename _Tp >
constexpr __conditional_t<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&> std::move_if_noexcept ( _Tp & __x )
constexprnoexcept
Conditionally convert a value to an rvalue.

Parameters
__x A thing of arbitrary type.
Returns
The parameter, possibly cast to an rvalue-reference.
Same as std::move unless the type's move constructor could throw and the type is copyable, in which case an lvalue-reference is returned instead.

Definition at line 125 of file move.h.

https://gcc.gnu.org/onlinedocs/gcc-12.1.0/libstdc++/api/a01588.html#ga0e32868df3e12ec3f230ea28545b6ea8

 

 

template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
typename conditional
<
    !is_nothrow_move_constructible<_Tp>::value && is_copy_constructible<_Tp>::value,
    const _Tp&,
    _Tp&&
>::type
#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
const _Tp&
#endif
move_if_noexcept(_Tp& __x) _NOEXCEPT
{
    return _VSTD::move(__x);
}

下面是展开后的代码:

template <class _Tp>
inline __attribute__ ((__visibility__("hidden"), __always_inline__)) constexpr

typename conditional
<
    !is_nothrow_move_constructible<_Tp>::value && is_copy_constructible<_Tp>::value,
    const _Tp&,
    _Tp&&
>::type



move_if_noexcept(_Tp& __x) noexcept
{
    return std::__1::move(__x);
}

 

forward

参考c++/v1/type_traits中的代码:

template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
_Tp&&
forward(typename std::remove_reference<_Tp>::type& __t) _NOEXCEPT
{
    return static_cast<_Tp&&>(__t);
}

另一种形式:

template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
_Tp&&
forward(typename std::remove_reference<_Tp>::type&& __t) _NOEXCEPT
{
    static_assert(!std::is_lvalue_reference<_Tp>::value,
                  "Can not forward an rvalue as an lvalue.");
    return static_cast<_Tp&&>(__t);
}

 

 

CV-qualifiers

CV-qualifiers翻译过来的意思就是“CV限定符”。这里的c其实指的就是const,v指的就是volatile。我们在定义变量和函数的时候,可以给变量指定const或者volatile,没有指定const或者volatile的变量类型被称为“cv-unqualified type”,而指定了const或者volatile的变量类型被称为“cv-qualified type”。

 

根据const或者volatile的限定,每一种“cv-unqualified type”的类型都对应3中“cv-qualified”版本的类型,即const-qualified版本的类型, volatile-qualified版本的类型, 以及const-volatile-qualified版本的类型。它们都属于不同的类型。

 

cv

写道
In this International Standard, the notation cv (or cv1 , cv2 , etc.), used in the description of types, represents
an arbitrary set of cv-qualifiers, i.e., one of {const}, {volatile}, {const, volatile}, or the empty set.
Cv-qualifiers applied to an array type attach to the underlying element type, so the notation “cv T,” where
T is an array type, refers to an array whose elements are so-qualified. An array type whose elements are
cv-qualified is also considered to have the same cv-qualifications as its elements. [ Example:
typedef char CA[5];
typedef const char CC;
CC arr1[5] = { 0 };
const CA arr2 = { 0 };
The type of both arr1 and arr2 is “array of 5 const char,” and the array type is considered to be constqualified. — end example ]

 

 

Constant expressions

 

 

constexpr

 

constexpr和const都是属于“const-qualified type”类型。

 

能用const的地方也能用constexpr。

 

constexpr变量必须初始化为一个常量表达式,即上面的“Constant expressions”。

 

int a = 10;

constexpr int b = a;

这里的a并不属于常量表达式。

 

constexpr int a2 = 10;

 

#define T 10

constexpr int a3 = T;

 

const int a1 = 10;

constexpr int a5 = a1;

这里的a1属于常量表达式

 

int a = 10;

const int a1 = a;

constexpr int a5 = a1;

这里的a1不属于常量表达式,因为a不属于常量表达式

 

const int a1 = 10;

int const a2 = a1;

constexpr int a5 = a2;

这里的a2属于常量表达式。

 

int a = 10;

const int a1 = a;

int const a2 = a1;

constexpr int a5 = a2;

这里的a2不属于常量表达式,因为a不属于常量表达式

 

 

 

constexpr function

 

写道
A constexpr specifier used in the declaration of a function that is not a constructor declares that function
to be a constexpr function. Similarly, a constexpr specifier used in a constructor declaration declares that
constructor to be a constexpr constructor. constexpr functions and constexpr constructors are implicitly
inline (7.1.2).

 

 

将一个constexpr函数赋值给一个constexpr变量。

 

constexpr int square(int x) 

{

  return x * x;

}

 

const int a1 = 10;

constexpr int a6 = square(a1);

 

constexpr constructor

 

 

函数

 

函数的定义

 

函数的声明

 

函数的调用

函数定义后,在调用前应该先进行声明

void fx1();

int main() 
{
  fx1();
}

void fx1() 
{
  printf("call fx1\n");
}

在VC下,函数定义后,如果在调用前没有先进行声明,则会报错:

int main() 
{
  fx1();
}

void fx1() 
{
  printf("call fx1\n");
}

注意这个程序虽然是c风格,但这里是c++程序,是cpp文件fntest2.cpp,而不是fntest2.c。

编译

>cl /c fntest2.cpp

Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for

80x86

Copyright (C) Microsoft Corp 1984-1998. All rights reserved.

 

fntest2.cpp

fntest2.cpp(5) : error C2065: 'fx1' : undeclared identifier

fntest2.cpp(10) : error C2373: 'fx1' : redefinition; different type modifiers

这里和以c程序的方式编译的结果报错有点不一样。

 

内存分配和回收

 

 

new&delete

 

C++中new&delete指的是什么?

 

int *a1 = new int(10);

int *a2 = new (std::nothrow) int(10);

 

int *a3 = new int[10];

 

C++中new是一种操作符(Operator)。

C++中new是一个表达式。

C++中new表示一些函数,也就是所谓的“allocation function”。

 

 

分配内存

C++继承了C语言的特性。也保留了C的malloc、calloc、realloc的动态内存分配的方式。

 

需要注意的是,malloc、calloc、realloc这几个函数返回的是一个void*指针类型,当我们需要某个类型的一块内存空间时,需要强制转换为指定类型的指针,如char *p = (char *) malloc(1024 * 1024 * 1024);在C语言中,void*指针可以隐式的和其他类型的指针进行转换。但在C++中不支持void*指针和其他类型的指针进行隐式转换,需要进行强制转换。

 

这种强制转换也可以通过static_cast进行,如下示例:

char *p = static_cast<char *>(malloc(1024 * 1024 * 1024));

 

C++还支持通过new的方式来为对象分配一块内存。

 

new-expression

 

A *a2 = new A("this is a2.");

 

 

delete-expression

 

 

内存分配和回收函数

即我们说的allocation function和deallocation function,也就是new和delete,这里new和delete指的不是operator,也不是new表达式或者delete表达式。

 

内存分配和回收函数都有好几种形式,包括new和delete,都有好几种形式。包括简单形式(即单一对象形式)、数组形式、以及Placement形式。

 

写道
void* operator new(std::size_t size);
void* operator new(std::size_t size, const std::nothrow_t&) noexcept;

这两种形式在程序中可以自定义自己的实现。

 

 

这里的“Replaceable”表示在程序中可以自定义以替换C++标准库中默认定义的版本。

 

 

_LIBCPP_NEW_DELETE_VIS void* operator new(std::size_t __sz)
#if !__has_feature(cxx_noexcept)
    throw(std::bad_alloc)
#endif
;

 

 

_LIBCPP_NEW_DELETE_VIS void* operator new(std::size_t __sz, const std::nothrow_t&) _NOEXCEPT _NOALIAS;

 

写道
void* operator new (std::size_t size, void* ptr) noexcept;

 

inline _LIBCPP_INLINE_VISIBILITY void* operator new  (std::size_t, void* __p) _NOEXCEPT {return __p;}

 

C++的这些allocation function和deallocation function,也就是new和delete,这些函数和一般的函数不太一样,函数定义的形式和使用都不一样。这些函数都是些操作符重载函数,new和delete这两个都是操作符。

 

内存分配失败

先看下通过C的方式分配内存失败的情况

  for (int i = 0;;i++)
  {
    char *p = (char *) malloc(1024 * 1024 * 1024);
    if (p == NULL) 
    {
      printf("malloc err.\n");
      return -1;
    }
  }

 

 

malloc: *** mach_vm_map(size=1073741824) failed (error code=3)

*** error: can't allocate region

*** set a breakpoint in malloc_error_break to debug

malloc err.

实际如果malloc失败的话,你可以看不到这么多错误信息,只能看到自己打印出来的“malloc err.”错误信息。

 

linkage-specification

 

写道
The string-literal indicates the required language linkage. This International Standard specifies the semantics
for the string-literals "C" and "C++". Use of a string-literal other than "C" or "C++" is conditionallysupported, with implementation-defined semantics. [ Note: Therefore, a linkage-specification with a stringliteral that is unknown to the implementation requires a diagnostic. — end note ] [ Note: It is recommended
that the spelling of the string-literal be taken from the document defining that language. For example, Ada
(not ADA) and Fortran or FORTRAN, depending on the vintage. — end note ]

 

 

namespace 

 

std

标准命名空间。

 

抽象类

含有纯虚函数的类为抽象类。

class A

{

public:

  virtual void a() = 0;

};

 

class B : public A

{

public:

  virtual void a()

  {

    cout<<"B::a()"<<endl;

  }

};

 

int main()

{

  A *b1 = new B();

  B *b2 = new B();

 

  b1->a();

  b2->a();

}

 

 

分配内存

栈上分配

堆上分配

 

释放内存

 

虚函数表

 

重载

 

全局重载

 

类函数重载

 

多态

 

压制多态

 

C++兼容C的语法,并在C的基础上进行了增强。

 

内联

 

offsetof

offsetof这是一个宏函数,并不是标准函数,标准库并不提供这个函数。并不是所有的编译器或者C库都会提供这个函数,Linux下gcc采用的glibc会提供这个函数,MacOS下gcc采用glibc的话也会提供这个函数。clang的话也会有这个函数。通常定义如下。

#define __offsetof(type, field) ((size_t)(&((type *)0)->field))

 

MacOS下(clang)标准库头文件stddef.h定义如下:

#define offsetof(t, d) __builtin_offsetof(t, d)

 

MacOS下stddef.h的定义是这样的:

 

在stddef.h头文件中包含了sys/_types.h、sys/_types/_offsetof.h这两个头文件。

sys/_types/_offsetof.h头文件中的定义:

#define offsetof(type, field) __offsetof(type, field)

sys/_types.h头文件中的定义:

#if defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 5 || __GNUC__ > 3)

#define __offsetof(type, field) __builtin_offsetof(type, field)

#else /* !(gcc >= 3.5) */

#define __offsetof(type, field) ((size_t)(&((type *)0)->field))

#endif /* (gcc >= 3.5) */

 

__builtin_offsetof是编译器内置的函数,也一定是一个宏。这里主要看下面的那个定义:

#define __offsetof(type, field) ((size_t)(&((type *)0)->field))

 

streambuf 

 

C++ streambuf protocol

 

 

查看程序依赖的链接库

# ldd Tl

linux-gate.so.1 =>  (0x00e06000)

libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x0023b000)

libm.so.6 => /lib/libm.so.6 (0x00e13000)

libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x0088c000)

libc.so.6 => /lib/libc.so.6 (0x00a16000)

/lib/ld-linux.so.2 (0x80089000)

 

Unix Programmer's Manual November 3, 1971,https://www.bell-labs.com/usr/dmr/www/1stEdman.html

 

Dennis M. Ritchie,https://www.bell-labs.com/usr/dmr/www/

 

内存对齐:

https://blog.csdn.net/alec1987/article/details/7362870

 

A draft rationale for the C99 standard:http://dl.iteye.com/topics/download/76434b4d-612c-3a9d-8fed-aad8e4fe5679

A late draft of C11 as of 2011-04-02:

http://www.open-std.org/jtc1/sc22/wg14/www/standards.html#9899

 

文件读写例子:

http://dl.iteye.com/topics/download/dea5a83d-6615-34de-9557-da33c5e59dac

 

C++ Observer 实现

 

 

void main() 
{
  
}
 

 

 

$ gcc test.c -o test
test.c: In function `main':
test.c:4: warning: return type of 'main' is not `int'
 

 

 

$ ./test.exe
greet.
 上面显示告警:warning: return type of 'main' is not `int', 但还是编译链接生成的可执行文件。如果想直接提示错误,可以指定-pedantic诊断选项,它可以输出标准要求的所有的诊断信息, 指定-pedantic-errors可以将这些诊断信息以错误的形式输出:

 

 

$ gcc -pedantic-errors test.c -o test
test.c: In function `main':
test.c:4: error: return type of 'main' is not `int'
 
// test
int main() 
{
  return 0;
}
 

 

$ gcc test.c -o test
 没有警告也没有错误

 

 

 

$ gcc -pedantic test.c -o test
test.c:1:1: warning: C++ style comments are not allowed in ISO C90
test.c:1:1: warning: (this will be reported only once per input file)
 有两个警告
$ gcc -pedantic-errors test.c -o test
test.c:1:1: C++ style comments are not allowed in ISO C90
test.c:1:1: (this will be reported only once per input file)
 

 

 如果遵循c89(也即是c90, ansi c)标准(指定-ansi-std=c90 or -std=iso9899:1990), //这种注释风格都不被支持:

$ gcc -ansi -pedantic test.c -o test
test.c:1: error: parse error before '/' token

 

$ gcc -std=c90 -pedantic test.c -o test
cc1: error: unrecognized command line option "-std=c90"

 

$ gcc -std=iso9899:1990 -pedantic test.c -o test
test.c:1: error: parse error before '/' token

其中,在我使用的gcc(gcc version 3.4.4),-std=c90不被支持。

从上面的警告信息看:warning: C++ style comments are not allowed in ISO C90,这种注释写法:

// test

不是ISO C90的注释风格,但怎么被认为是C++ style的注释风格?

 

如果采用c99标准(指定-std=c99或者-std=iso9899:1999),就不会报错:

$ gcc -std=c99 -pedantic-errors test.c -o test

可以看出//这种注释风格在c99标准之前是不被支持的。

 

C++标准

写道
C++ standards is available on the ISO C++ committee’s web site at http://www.open-std.org/jtc1/sc22/wg21/

 

标准库

 

stdc++库

写道
The GNU C++ Library
https://gcc.gnu.org/onlinedocs/libstdc++

 

写道
The GNU C++ Library Manual
https://gcc.gnu.org/onlinedocs/libstdc++/manual/index.html

 

写道
The GNU C++ Library API Reference
https://gcc.gnu.org/onlinedocs/libstdc++/api.html

 

写道
libstdc++ Source Documentation
https://gcc.gnu.org/onlinedocs/gcc-12.1.0/libstdc++/api/

 

 

libstdc++.so

写道
libstdc++ is part of GCC, the primary source for installation instructions is the GCC install page.

 

编译器

#include <iostream>

class cl
{
private:
  int i;

public:
  cl(int i) 
  {
    this->i = i;
  }

  int get()
  {
    return this->i;
  }
};

int main()
{
  cl cl1(100);

  std::cout<<"i="<<cl1.get()<<std::endl;
  return 0;
}

 

g++

以上面的例子为例:

 

>g++ "c++gcc_test.cpp" -o "c++gcc_test"

".\c++gcc_test"

 

c++

写道
On many systems, g++ is also installed with the name c++.

 

>c++ "c++gcc_test.cpp" -o "c++gcc_test"

".\c++gcc_test"

 

gcc

GCC不只是可以编译C,它还可以编译C++。

 

以上面的例子为例:

>gcc "c++gcc_test.cpp" -o "c++gcc_test" -lstdc++

>".\c++gcc_test"

和上面的g++编译不同的是,通过gcc编译c++的时候只是指定了一个stdc++库:-lstdc++

 

>ldd "c++gcc_test.exe"

        ntdll.dll => /cygdrive/c/WINDOWS/system32/ntdll.dll (0x7c92000

0)

        kernel32.dll => /cygdrive/c/WINDOWS/system32/kernel32.dll (0x7

c800000)

        cygwin1.dll => /usr/bin/cygwin1.dll (0x61000000)

        cygstdc++-6.dll => /usr/bin/cygstdc++-6.dll (0x6f9a0000)

        cyggcc_s-1.dll => /usr/bin/cyggcc_s-1.dll (0x6ff90000)

 

下面是linux下的编译链接

# gcc c++gcc_test.cpp -o c++gcc_test -lstdc++

# ./c++gcc_test

 

# ldd c++gcc_test

linux-gate.so.1 =>  (0x00f76000)

libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00871000)

libc.so.6 => /lib/libc.so.6 (0x00665000)

libm.so.6 => /lib/libm.so.6 (0x00f7f000)

/lib/ld-linux.so.2 (0x800cb000)

 

libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x001a8000)

 

 

#include <vector>

#include "Observer.hpp"

 

#ifndef OBSERVABLE

#define OBSERVABLE

class Observable

{

private:

std::vector<Observer *> observers;

 

public:

Observable();

 

void registerObserver(Observer &o);

 

void deregisterObserver(Observer &o);

 

void notifyObservers();

 

void notifyObservers(void *arg);

 

void clearObservers();

 

int getCountOfObserver();

};

#endif

 

====================================

 

#ifndef OBSERVER

#define OBSERVER

 

class Observable;

 

class Observer

{

public:

virtual void update(Observable* const o, void *arg) = 0;

};

 

#endif

 

===================================

 

#include <stdlib.h>

#include <vector>

#include "Observable.hpp"

 

Observable::Observable()

{

 

}

 

void Observable::registerObserver(Observer &o) 

{

observers.push_back(&o);

}

 

void Observable::deregisterObserver(Observer &o) 

{

for (std::vector<Observer *>::iterator iter = observers.begin(); iter != observers.end(); ++iter)

{

if (*iter == &o)

{

observers.erase(iter);

break;

}

}

}

 

void Observable::notifyObservers()

{

notifyObservers(NULL);

}

 

void Observable::notifyObservers(void *arg)

{

for(std::vector<Observer *>::iterator iter = observers.begin(); iter != observers.end(); ++iter)

{

Observer *observer = (Observer *) (*iter);

observer->update(this, arg);

}

}

 

void Observable::clearObservers()

{

observers.clear();

}

 

 

int Observable::getCountOfObserver()

{

return observers.size();

}

 

=========================================

 

#include <stdio.h>

#include <assert.h>

#include "../lang/Observer.hpp"

#include "../lang/Observable.hpp"

 

class GenericObserver : public Observer

{

void update(Observable* const o, void *arg)

{

char *command = (char *) arg;

printf("[COMMAND] %s\n", command);

}

};

 

void testGetCountOfObserver() 

{

printf("test getCountOfObserver\n");

Observable o;

int count = o.getCountOfObserver();

printf("%d observers\n", count);

assert(count == 0);

}

 

void testRegisterObserver()

{

printf("test registerObserver\n");

Observable o;

int count = o.getCountOfObserver();

printf("%d observers\n", count);

assert(count == 0);

 

 

Observer *observer1 = new GenericObserver();

o.registerObserver(*observer1);

count = o.getCountOfO

 

C++难在哪里?

关于C++是一种高级语言还是低级语言,首先要说的是C++继承了C的语言特性,保留了C的所有能力,具备底层操作的能力,能够更贴近底层硬件编程,如针对硬件进行驱动编程、对内存直接操作等。所以C++够得上低级。这无疑增加了C++的学习使用的难度。

 

尽管C也具备这些能力,但C难吗?尽管C语言本身并不复杂,但C本身就作为系统编程语言,一种低级语言具备底层操作的能力,能够更贴近底层硬件编程,在语言上已经相当简单了。尽管使用C在编程的时候并不容易,也是使用上的困难,这些困难并不是C语言本身的,而是系统上的。

C++的难度还在语言本身上,这并不仅仅体现在语法特性上,这只是表面,更深层的原因在C++语言设计的抽象机。编程语言表面上是那些语法特性,但本质是编程语言的抽象机设计。尤其是对于高级语言来说,设计出来就应该更简单。

 

 

分享到:
| Tree
评论

相关推荐

    C++C++C++C++C++C++C++

    C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++C++

    c++代码 c++代码 c++代码

    c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++代码c++...

    C++98、C++03、C++11、C++14、C++17、C++20的CHM查询文档

    内容包含:C++11 C++14 C++17 C++20 注释 C++ 编译器支持情况表 独立与宿主实现 C++ 语言 C++ 关键词 预处理器 C++ 标准库头文件 具名要求 功能特性测试 (C++20) 工具库 类型支持(基本类型、RTTI、类型特性) 概念...

    c++狼人杀 c++狼人杀

    c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀c++狼人杀...

    C++编程实例100篇

    《C++编程实例100篇》是一本深入浅出的C++编程教程,它以实践为主导,通过丰富的实例帮助学习者掌握C++语言的基础和核心概念。这本书的每个实例都精心设计,旨在帮助初学者和有经验的开发者巩固和提升C++编程技能。 ...

    C++面试题笔试题C++ 数据结构算法笔试题资料合集.zip

    C++面试题笔试题C++ 数据结构算法笔试题资料合集: 50个C、C++面试题.pdf C++ 数据结构、算法笔试题.docx C++基础面试题.docx C++开发工程师面试题库.docx C++技能测试试卷一及答案.docx C++技能测试试卷二及答案....

    c++各种小游戏(我们老师的)

    【标题】:“C++各种小游戏(我们老师的)” 在C++编程领域,开发小游戏是一种非常有效的学习实践方式,尤其对于初学者来说。本资源集合包含了我们老师精心制作的一系列C++小游戏,旨在帮助学生深入理解和掌握C++...

    华为c++编码规范&c/c++安全编码规范

    华为c++编码规范和安全编码规范最新3.1版本 华为c++编码规范和安全编码规范最新3.1版本 华为c++编码规范和安全编码规范最新3.1版本 华为c++编码规范和安全编码规范最新3.1版本 华为c++编码规范和安全编码规范最新3.1...

    Dev C++ 6.3安装包,DevC++智能开发平台

    Dev C++是一款轻量级的C++集成开发环境(IDE),专为初学者和专业开发者提供简洁、高效的编程环境。这个6.3版本是其历史上的一个重要里程碑,它结合了GCC编译器(GNU Compiler Collection)和一个用户友好的界面,...

    C++大作业坦克大战源码.zip

    C++大作业坦克大战源码C++大作业坦克大战源码C++大作业坦克大战源码C++大作业坦克大战源码C++大作业坦克大战源码。C++大作业坦克大战源码C++大作业坦克大战源码C++大作业坦克大战源码C++大作业坦克大战源码C++大作业...

    C++语言导学 A Tour of C++(C++之父写的入门书)

    《计算机科学丛书:C++语言导学》作者是C++语言的设计者和最初实现者,写作本书的目的是让有经验的程序员快速了解C++现代语言。书中几乎介绍了C++语言的全部核心功能和重要的标准库组件,以很短的篇幅将C++语言的...

    C++飞机大战 C++课程设计

    C++飞机大战 C++课程设计C++飞机大战 C++课程设计C++飞机大战 C++课程设计C++飞机大战 C++课程设计C++飞机大战 C++课程设计C++飞机大战 C++课程设计C++飞机大战 C++课程设计C++飞机大战 C++课程设计C++飞机大战 C++...

    c++builder6安装包

    C++Builder 6是一款由Borland公司(后被Embarcadero Technologies收购)开发的集成开发环境(IDE),主要用于C++编程语言的应用程序开发。它结合了强大的编译器、调试器、可视化设计工具和其他实用功能,为开发者...

    c++小游戏 c++小游戏

    c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏c++小游戏...

    C++大作业飞机大战源码.zip

    C++大作业飞机大战源码C++大作业飞机大战源码C++大作业飞机大战源码C++大作业飞机大战源码C++大作业飞机大战源码C++大作业飞机大战源码C++大作业飞机大战源码C++大作业飞机大战源码C++大作业飞机大战源码C++大作业...

    小熊猫devc++下载包

    小熊猫devc++下载包小熊猫devc++下载包小熊猫devc++下载包小熊猫devc++下载包小熊猫devc++下载包小熊猫devc++下载包小熊猫devc++下载包小熊猫devc++下载包小熊猫devc++下载包小熊猫devc++下载包小熊猫devc++下载包小...

    Visual C++游戏开发经典案例详解.pdf

    《Visual C++游戏开发经典案例详解》这本书是针对使用Visual C++进行游戏开发的专业指南,旨在帮助读者通过实例学习和掌握C++编程语言在游戏开发中的应用。书中的内容覆盖了从基础到高级的游戏开发技术,包括图形...

    Effective Modern C++:改善C++11和C++14的42个具体做法(中文版 + 英文版)

    《Effective Modern C++:改善C++11和C++14的42个具体做法(影印版)(英文版)》中包括以下主题:剖析花括号初始化、noexcept规范、完美转发、智能指针make函数的优缺点;讲解std∷move,std∷forward,rvalue引用和...

    基于C++语言开发的军旗游戏完整源码

    基于C++语言开发的军旗游戏完整源码 基于C++语言开发的军旗游戏完整源码 基于C++语言开发的军旗游戏完整源码 基于C++语言开发的军旗游戏完整源码 基于C++语言开发的军旗游戏完整源码 基于C++语言开发的军旗游戏完整...

    21天学通C++(第五版) vs2008程序打包 深入浅出MFC 浙大教材C++达内 C++ 华为C++培训资料 visual c++_MFC

    21天学通C++(第五版) vs2008程序打包 深入浅出MFC 浙大教材C++达内 C++ 华为C++培训资料 visual c++_MFC 资源内容: visual c++_MFC 达内 C++ C++课件.ppt c++源码 .rar Core C++ Programming_new.ppt Core C++ ...

Global site tag (gtag.js) - Google Analytics