开发者

C++ constructor syntax explaination

开发者 https://www.devze.com 2023-02-13 17:41 出处:网络
I was going through a tutorial for building an AST with the help of Clang/LLVM. I see this syntax there:

I was going through a tutorial for building an AST with the help of Clang/LLVM.

I see this syntax there:

struct PPContext {
  // Takes ownership of client.
  PPContext(clang::DiagnosticClient* client = 0,
            const std::string& triple = LLVM_HOSTTRIPLE)
    : diagClient(client == 0?new clang::TextDiagnosticPrinter:client),
      diags(diagClient),
      target(clang::TargetInfo::CreateTargetInfo(triple)),
      headers(fm),
      pp(diags, opts, *target, sm, headers)
  {
    // Configure warnings to be similar to what command-line `clang` outputs
    // (see tut03).
    // XXX: move warning initialization to libDriver
    using namespace clang;
    diags.setDiagnosticMapping(diag::kind,diag::MAP_IGNORE);
//diag::warn_pp_undef_identifier was the initial value instead of diag::kind. But I changed since it gave error.
  }

  ~PPContext()
  {
    delete diagClient;
    delete target;
  }

  clang::DiagnosticClient* diagClient;
  clang::Diagnostic diags;
  clang::LangOptions opts;
  clang::TargetInfo* target;
  clang::SourceManager sm;
  clang::FileManager fm;
  clang::HeaderSearch headers;
  clang::Preprocessor pp;
};

And:

//What is the constructor doing here ? The construct looks very different and difficult to comprehend !!!
// Could someone break it up for me ?
PPContext(clang::DiagnosticClient* client = 0,
            const std::string& triple = LLVM_HOSTTRIPLE)
    : diagClient(client == 0?new clang::TextDiagnosticPrinter:client),
      diags(diagClient),
      target(clang::TargetInfo::CreateTargetInfo(triple)),
      headers(fm),
      pp(diags, opts, *target, sm, headers)
  {
    // Configure warnings to be similar to what command-line `clang` outputs
    // (see tut03).
    // XXX: move warning initialization to libDriver
    using namespace clang;
    diags.setDiagnosticMapp开发者_StackOverflow社区ing(diag::kind,diag::MAP_IGNORE);
//diag::warn_pp_undef_identifier was the initial value instead of diag::kind. But I changed since it gave error.
  }

Please let me know if there is any other material which would be of good help and learning experience. Thanks


These are constructor initializers. They initialized class members with the value given to them. For instance:

class TestClass
{
private:
    int someField;

public:
    TestClass() : someField(5) { }
};

Will initialize the member someField to have a value of 5 during the call to the TestClass() constructor. You can separate multiple initializers with a , to initialize multiple members. You can also pass parameters from the constructor to these initializers such as:

class TestClass
{
private:
    int someField;

public:
    TestClass(int _someField) : someField(_someField) { }
};

When this constructor is called, the value passed to _someField will be used to initialize someField.

Also consider inheritance. Using the second TestClass as our base we get the following derived type:

class TestClassDerived : public TestClass
{
public:
    TestClassDerived(int _someField) : TestClass(_someField) { }
};

That's how you can construct a base class from a derived type and pass parameters to a non-default constructor. Without this you wouldn't be able to construct the base with the appropriate parameters using a non-default constructor.


It's called a constructor initialization list, which is used for inheritance and initializating member variables. Click this link for a good explanation of this topic.

One scenario this is required is dealing with inheritance. Consider the following:

class Base
{
public:
    Base(int n)
    {
    }
};

class Derived : Base
{
public:
    // Error! How do we construct Base? We never pass n
    // to the constructor of Base.
    Derived(int n)
    {
    }
};

How can we change the above to compile? With a constructor initialization list:

class Base
{
public:
    Base(int n)
    {
    }
};

class Derived : Base
{
public:
    // Now your compiler is happy.
    Derived(int n) : Base(n)
    {
    }
};


This constructur is in the format

PPContext(arg1, arg2)
    : initConstructor1,
      ...,
      initConstructor5

where you can exchange initConstructor to the initialization constructors of the PPContext members

0

精彩评论

暂无评论...
验证码 换一张
取 消