Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何制作C++;适合干洗吗? 在C++中,如果我们在一些基类(比如BASE)中有一些虚函数,我们想重写这个虚拟函数,我们必须再次声明这个虚拟函数,使它在派生类中甚至编译。 class Base { public: virtual void virtualFunction(); static int s_whatSoEver[]; private: void _privateFunction(); } class Derived { public: virtual void virtualFunction(); }_C++_Dry - Fatal编程技术网

如何制作C++;适合干洗吗? 在C++中,如果我们在一些基类(比如BASE)中有一些虚函数,我们想重写这个虚拟函数,我们必须再次声明这个虚拟函数,使它在派生类中甚至编译。 class Base { public: virtual void virtualFunction(); static int s_whatSoEver[]; private: void _privateFunction(); } class Derived { public: virtual void virtualFunction(); }

如何制作C++;适合干洗吗? 在C++中,如果我们在一些基类(比如BASE)中有一些虚函数,我们想重写这个虚拟函数,我们必须再次声明这个虚拟函数,使它在派生类中甚至编译。 class Base { public: virtual void virtualFunction(); static int s_whatSoEver[]; private: void _privateFunction(); } class Derived { public: virtual void virtualFunction(); },c++,dry,C++,Dry,如果我们想改变虚拟函数原型,就必须改变派生函数的每个声明,这不是很愚蠢吗 另外,为什么需要在头文件中声明一些受保护的或私有的函数,因为头文件用于公共接口定义,而使用此接口的用户根本不需要关心它们?也许我们可以直接实现并声明.cpp文件中的私有或受保护函数,就像Objective-C一样 C++也没有静态初始值设定项,如果我们想初始化某个静态类变量,我们必须为此创建一个类: class BaseStaticVariableInitializer { public: BaseStaticVa

如果我们想改变虚拟函数原型,就必须改变派生函数的每个声明,这不是很愚蠢吗

另外,为什么需要在头文件中声明一些受保护的或私有的函数,因为头文件用于公共接口定义,而使用此接口的用户根本不需要关心它们?也许我们可以直接实现并声明.cpp文件中的私有或受保护函数,就像Objective-C一样

C++也没有静态初始值设定项,如果我们想初始化某个静态类变量,我们必须为此创建一个类:

class BaseStaticVariableInitializer {
public:
    BaseStaticVariableInitializer() {
        Base::s_whatSoEver = new int[20];
        for (int i = 0; i < 20; i++) {
            s_whatSoEver[i] = xxx;
        }
    }
    ~BaseStaticVariableInitializer() {
         delete [] Base::s_whatSoEver;
    }
}
对不起,我是无知的,但是你写C++代码的正确方法是什么?p> 如果我们想改变虚拟函数原型,就必须改变派生函数的每个声明,这不是很愚蠢吗

否。如果您正在更改基类中的虚拟函数原型,则您正在更改公共接口。你不应该那样做

另外,为什么需要在头文件中声明一些受保护的或私有的函数,因为头文件用于公共接口定义,而使用此接口的用户根本不需要关心它们

受保护的
成员应被视为类的公共接口的一部分。
protected
只会帮助您避免错误,否则,您可能会因为这些错误
公开而面临风险。但是请不要搞错:
受保护的
成员是类接口的一部分,应该这样对待。

关于头文件中的
private
s:是的,我同意,在许多方面,只将它们保存在实现文件中更符合逻辑。但是,考虑通过值传递类时:

foo(Bacon b)
{
    b.cook();
}
为了调用
foo()
,编译器需要有完整的
Bacon
类定义。(注意:只有类定义,而不是它的成员函数的定义。)这样编译器就可以知道在调用
foo()
时要为类分配多少堆栈空间。如果编译器还必须搜索实现文件以查找
private
变量,那么解析将更加复杂(编译可能会更慢)

更新 既然你提到了DRY,我必须指出这一点。DRY原则规定:

在一个系统中,每一项知识都必须有一个单一的、明确的、权威的表示

在相关类中声明虚拟函数并不违反这一原则。它们的功能不同。在
Base
中,您声明
Base::foo
virtual
。在
Derived
中,您声明
Derived::foo
也是
virtual
Base::foo
Derived::foo
是两个独立的函数,但恰好可以通过指向
Base
的指针或引用来调用这两个函数。 1)对于第一个问题,请参阅C++中的重载与重载的区别 2] 初始化静态memebr,这可以在静态成员函数中完成

class Base {
public:
  virtual void virtualFunction();
  static int s_whatSoEver[];

  static void BaseStaticVariableInitializer() {
    Base::s_whatSoEver = new int[20];
    for (int i = 0; i < 20; i++) {
        s_whatSoEver[i] = xxx;
    }
}
private:
 void _privateFunction();
如果我们想改变虚拟函数原型,就必须改变派生函数的每个声明,这不是很愚蠢吗

这正是重点。如果基中的签名发生更改,您希望编译器告诉您,而不是试图用错误的类型调用函数。C++是一种静态类型的编译语言。这些类型是在编译时定义的,如果虚拟函数的类型发生更改,则需要重新编译以适应更改

为什么需要在头文件中声明一些受保护的或私有的函数,因为头文件用于公共接口定义,而使用此接口的用户根本不需要关心它们

这也是一种完全相同的设计选择。在C++中,一个定义规则要求每个类型在所有翻译单元(不同编译的文件)中完全相同。如前所述,C++是一种编译语言,一般来说,成员影响类,而不管访问说明符(在编译过程中被丢弃)。当编译器创建您的类型的对象时,它必须为每个和所有数据成员分配足够的空间,无论它们是公共的、私有的还是受保护的。在构建虚拟表时,它需要知道需要为所有函数分配多少插槽。可以说,非虚拟函数不会影响生成的object/RTTI,但它们可能会影响生成的object/RTTI

如果在基类中添加的新虚拟函数与派生类中的受保护/私有成员函数具有完全相同的签名,则后者将成为前者的重写,需要在虚拟表中创建一个新插槽。虽然这可能不太可能,但如果函数隐藏在单个翻译单元中(您可能有权访问或无权访问),则可能会遇到这些问题

C++也没有静态初始值设定项,如果我们想初始化某个静态类变量,我们就必须为此创建一个类

C++没有静态初始值设定项,但我肯定不会为它创建类。静态成员变量需要在单个转换单元中定义,并且可以在该转换单元中初始化。在简单的情况下,您可以直接执行常规初始化,对于更复杂的情况,您可以创建一个函数来提供初始化值

int *Base::member = new int[10](); // value initialized (set to 0)

// abusing lambdas not to write a function:
int *Base::member2 = []()->int* { 
                         int *p = new int[10];
                         for (int i = 0; i < 10; ++i) p[i] = xxx;
                         return p; }();
int*
 static int Base::s_whatSoEver[20];
int *Base::member = new int[10](); // value initialized (set to 0)

// abusing lambdas not to write a function:
int *Base::member2 = []()->int* { 
                         int *p = new int[10];
                         for (int i = 0; i < 10; ++i) p[i] = xxx;
                         return p; }();
std::unique_ptr<int[]> Base::member(new int[10]());