Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.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++_This_Language Lawyer_Initializer List - Fatal编程技术网

C++ 在初始值设定项列表中使用此选项

C++ 在初始值设定项列表中使用此选项,c++,this,language-lawyer,initializer-list,C++,This,Language Lawyer,Initializer List,假设我有一个类Baz,它按顺序继承自类Foo和Bar。类Bar的构造函数获取指向Foo对象的指针。我想做的是将this作为Foo对象传递给Bar构造函数: Baz () : Foo(), Bar(this) {} 一个有效的例子: #include <iostream> class Bar; class Foo { public: virtual ~Foo() {} virtual void parse_bar (Bar&) const = 0; }; c

假设我有一个类
Baz
,它按顺序继承自类
Foo
Bar
。类
Bar
的构造函数获取指向
Foo
对象的指针。我想做的是将
this
作为
Foo
对象传递给
Bar
构造函数:

Baz () : Foo(), Bar(this) {}
一个有效的例子:

#include <iostream>
class Bar;
class Foo {
  public:
  virtual ~Foo() {}
  virtual void parse_bar (Bar&) const = 0;
};  

class Bar {
  private:
  const Foo * parser;
  public:
  Bar (const Foo * parser_in) : parser(parser_in) {}
  virtual ~Bar() {}
  void parse_self () { parser->parse_bar (*this); }
};  

class Baz : public Foo, public Bar {
  public:
  Baz () : Foo(), Bar(this) {}
  virtual void parse_bar (Bar &) const { std::cout << "Hello World\n"; }
};

int main () {
  Baz baz;
  baz.parse_self();
}
#包括
分类栏;
福班{
公众:
虚拟~Foo(){}
虚空解析_bar(bar&)const=0;
};  
分类栏{
私人:
constfoo*解析器;
公众:
Bar(const Foo*parser_in):parser(parser_in){
虚拟~Bar(){}
void parse_self(){parser->parse_bar(*this);}
};  
Baz类:公共餐厅、公共酒吧{
公众:
Baz():Foo(),Bar(this){}

虚虚空PARSEBAR(bar & const){STD::CUT

它是好的。C++标准实际上澄清了使用< <代码> < /COD>指针在初始化列表中:

12.6.2初始化基和成员[class.base.init]

段落7:
mem初始值设定项
表达式列表中的名称在指定
mem初始值设定项
的构造函数范围内进行评估。[示例:

初始化
X::r
要参考
X::a
,请使用 构造函数参数
i
的值,用 构造函数参数
i
的值,并且使用
X::i
的值;每次类的对象
X
已创建。][注意:因为
mem初始值设定项
是在 构造函数的范围,
指针可用于
mem初始值设定项的表达式列表
,用于引用正在创建的对象 已初始化。]

Baz
的初始值设定项中的
指针的类型实际上是
Baz
类型。当然,您必须注意的是,并非所有成员都已初始化。许多(如果不是全部的话)编译器将其设置为最高警告级别(无论如何,您确实应该这样做)将警告您将
指针传递到基类

但是,看起来您正在使它变得更加复杂。为什么不将虚拟函数
parse_bar()
放在
bar
类中,而忘记
Foo
类呢

#include <iostream>

class Bar
{             
public:      
    Bar() {}      
    virtual ~Bar() {}      
    void parse_self () { parse_bar(); } 
private: // Template method pattern
    virtual void parse_bar() const = 0;         
};        

class Baz : public Bar
{      
public:      
    Baz () {}     
private: // Yes, this does override the private `parse_bar()` member!
    virtual void parse_bar() const { std::cout << "Hello World\n"; }      
};

int main ()
{ 
    Baz baz; 
    baz.parse_self(); 
} 
#包括
分类栏
{             
公众:
Bar(){}
虚拟~Bar(){}
void parse_self(){parse_bar();}
私有模板方法模式
虚空解析_bar()常量=0;
};        
Baz类:公共酒吧
{      
公众:
Baz(){}
private://是的,这会覆盖private`parse_bar()`成员!

virtualvoid parse_bar()const{std::cout在这种情况下有两点需要注意

首先,在构造函数初始值设定项列表中,此
指针指的是未构造(或未完全构造)的对象。可以访问此类指针,但它所指的对象只能以有限的方式使用。请参见语言规范中的12.7

其次,在您的具体示例中,您实际正在做的是在尝试任何访问之前将
指针转换为
Foo*
类型。这是完全安全的,因为此时
Foo
子对象已完全构建。(我假设,接下来的任何访问(如果有的话)都将仅限于完全构造的
Foo
子对象)


唯一值得关注的是,在这种情况下,将
this
转换为
Foo*
类型是否合法,即转换过程本身是否应该成功。答案是:是的,在普通(非虚拟)继承的情况下,这种转换是完全合法和安全的(同样,在12.7中明确允许)

@GManNickG Dont!这些评论可能对你的工作有用newbies@Evgeni:对不起。:)新手!关于类继承的问题?->。谢谢,AndreyT。呼。这将帮助我摆脱僵局。+1,很好的答案,电子版。选择哪个答案很难。关于我发布的代码和你建议的修复:我的代码是为了说明用法而设计的;一个MWE。它看起来与我必须处理的代码完全不同。
#include <iostream>

class Bar
{             
public:      
    Bar() {}      
    virtual ~Bar() {}      
    void parse_self () { parse_bar(); } 
private: // Template method pattern
    virtual void parse_bar() const = 0;         
};        

class Baz : public Bar
{      
public:      
    Baz () {}     
private: // Yes, this does override the private `parse_bar()` member!
    virtual void parse_bar() const { std::cout << "Hello World\n"; }      
};

int main ()
{ 
    Baz baz; 
    baz.parse_self(); 
}