首頁  >  問答  >  主體

c++11 - c++里面类成员为什么不能做为类成员函数的默认实参?

class TestClass
{
public:
    TestClass() = default;
    ~TestClass() = default;

public:
    int func(int j = i)
    {
        cout << i << endl;
    }

private:
    int i = 1;
};

比如这样 这样会报错 为什么?

伊谢尔伦伊谢尔伦2714 天前551

全部回覆(4)我來回復

  • PHPz

    PHPz2017-04-17 13:35:09

    原答案部分有誤,重新回答。

    靜態變數可以作為預設實參,不需要一定是常數。實例如下:

    #include <iostream>
    
    class A {
    public:
        explicit A(int mm = n) : m(mm) {}
        int get() const { return m; }
        int foo(int i = n) const { return i; }
        static void set(int nn) { n = nn; }
    
    private:
        int m;
        static int n;
    };
    
    int A::n = 1;
    
    int main() {
        A a1;
        A a2(2);
        std::cout << "a1: foo() " << a1.foo() << " get() " << a1.get() << std::endl;
        std::cout << "a2: foo() " << a2.foo() << " get() " << a2.get() << std::endl;
        A::set(3);  //a1.set(3);  //a2.set(3);
        std::cout << "A::set(3)" << std::endl;
        std::cout << "a1: foo() " << a1.foo() << " get() " << a1.get() << std::endl;
        std::cout << "a2: foo() " << a2.foo() << " get() " << a2.get() << std::endl;
        A a3;
        std::cout << "a3: foo() " << a3.foo() << " get() " << a3.get() << std::endl;
        
        return 0;
    }
    

    原答案

    靜態常數可以,如下兩種定義都可以。

    static const int i;
    static constexpr int i;

    當然,靜態常數的初始化是另一回事了。

    具體例子請參考《C++ Primer》第五版,7.6節,與靜態成員的使用相關的部分。

    回覆
    0
  • 怪我咯

    怪我咯2017-04-17 13:35:09

    這個在C++裡面是不行的,雖然C++規定了參數的壓棧順序,但是標准上沒有規定參數的初始化順序,我覺得這是最大的原因,這樣子 你也不能這麼做

    int func(int m, int n = m); // 这中写法不行,包括上面你例子中的j = this->i,
    //个人觉得还有一个原因就是this或者m是最后压栈的,
    //n = m或者j = this->i 并不能访问到m或者this
    
    int func(int m = n, int n = 10); //虽然说理论上n是比m会早一步压人栈中,
    //但是因为没有规定初始化顺序所以这种写法不对

    而且這種寫法 編譯期產生程式碼的時候估計會很麻煩,預設參數可以使用靜態的或字面值
    有些其它語言是支援這種使用非靜態成員寫法的

    貼一段標準

    ISO C++ section 8.3.6/9
    a nonstatic member shall not be used in a default argument expression, even if it is 
    not evaluated, unless it appears as the id-expression of a class member access 
    expression (5.2.5) or unless it is used to form a pointer to member (5.3.1).
    ISO C++ section 8.3.6/9
    Default arguments are evaluated each time the function is called. The order of 
    evaluation of function arguments is unspecified. Consequently, parameters of a function
    shall not be used in default argument expressions, even if they are not evaluated.

    當然也有不錯的解決方案,使用重載

    int func(int j);
    int func()
    {
        func(this->i);
    }
    • 參考

      http://stackoverflow.com/questions/4539406/nonstatic-member-as-a-default-argument-of-a-nonstatic-member-function

    回覆
    0
  • 巴扎黑

    巴扎黑2017-04-17 13:35:09

    因為在func(int j = i)時,this是第零個參數,第一個參數看不見this,自然沒有辦法取到this->i,就好比:

    class A {
    public:
        int a = 1;
    };
    class B {
    public:
        int func(A* a, int j = a->i) {
        //do something
        }
    };
    
    int main(){
        A a;
        B b;
        b.func(&a);
    }
    

    這裡func的第二個參數沒用到第一個參數裡的a。

    回覆
    0
  • 黄舟

    黄舟2017-04-17 13:35:09

    class TestClass
    {
    public:
        TestClass() = default;
        ~TestClass() = default;
    
    public:
        int func(int j = i)
        {
            cout << i << endl;
        }
    
    private:
        int i = 1; //这里
    };
    

    成員變數可以是成員函數的預設實參,你的出錯的問題不在這裡,是你的成員變數初始化有問題。
    在成員變數的定義的進行初始化,這種寫法不對。

    你private下面只能定義成員變量,或是初始化靜態變數。普通成員變數的初始化是在建構函式裡完成的。

    
    
    class TestClass
    {
    public:
        TestClass():i(1){};
    
    public:
        int func(int j = i)
        {
            cout << i << endl;
        }
    
    private:
        int i;
    };
    

    回覆
    0
  • 取消回覆