【问题标题】:c++ default parameters class membersc++ 默认参数类成员
【发布时间】:2015-01-09 18:22:34
【问题描述】:
class bst
{
private:

typedef struct nod
{
  int data;
  nod* left;
  nod* right;
  nod(int key):data(key),left(NULL),right(NULL){}
}node;
 node* root;

public:

void create();
void add(int key,node*curr=root);
void c2ll();
void print(){}

代码无法编译... 我收到以下错误。

ain.cpp: In function ‘int main()’:
main.cpp:7:12: error: call to ‘void bst::add(int, bst::node*)’ uses the default argument for parameter 2, which is not yet defined
   bt.add(50);
            ^
In file included from bst.cpp:1:0:
bst.h:14:8: error: invalid use of non-static data member ‘bst::root’
  node* root;
        ^
bst.h:19:28: error: from this location
 void add(int key,node*curr=root);
                            ^
bst.h:14:8: error: invalid use of non-static data member ‘bst::root’
  node* root;
        ^
bst.cpp:10:34: error: from this location
 void bst::add(int key,node* curr=root)

欢迎提出任何建议...我试图避免编写包装方法,而是使用 c++ 提供的默认功能

【问题讨论】:

  • 正如错误所说,您不能将默认参数设置为非静态成员变量。您应该重载 add 以仅获取键并调用具有两个参数的键,并将 root 作为第二个参数。
  • @Borgleader:你应该这样回答。
  • 那么,这相当于编写一个包装函数。无论如何我可以不写那个包装函数吗?

标签: c++ class parameters default members


【解决方案1】:

根据 C++ 标准(8.3.6 默认参数)

  1. ...同样,一个非静态成员不得在默认参数中使用,即使它没有被评估,除非它显示为 类成员访问表达式 (5.2.5) 的 id-expression 或除非它 用于形成指向成员(5.3.1)的指针。 [ 示例: 以下示例中 X::mem1() 的声明格式不正确 因为没有为用作的非静态成员 X::a 提供对象 一个初始化器。
int b;
class X {
int a;
int mem1(int i = a); // error: non-static member a
// used as default argument
int mem2(int i = b); // OK; use X::b
static int b;
};

你可以重载函数add。例如

void add( int key );

void add( int key, node *curr );

第一个函数默认使用root。它可以简单地调用第二个函数,将节点根作为第二个参数传递。

【讨论】:

  • 我遇到的问题是它是一个递归函数...void add(int key);....我需要每个堆栈帧中的节点*,因此我将其设为参数
  • @basav 正如我在更新后的帖子中所写,第一个函数可以调用第二个递归函数。:) 所以没有问题。
  • @basav 通常这种方法用于递归函数 void reverse( char *s )。函数本身不是递归的,但它调用重载函数 void reverse( char *s, size_t n ) 像 reverse( s, strlen( s ) );
【解决方案2】:

问题出在方法的定义中:

void add(int key,node*curr=root);

root 未在您使用它的上下文中定义。如果你的意思是成员变量node* root,在成员函数中是没有办法默认成员变量的,但是你可以将NULL(0)设置为默认值并在定义中检查。

void bst::add ( int key,node*curr=NULL)
{
     if(curr==NULL) {
         curr= this->root;
     }
}

【讨论】:

  • 同意参数和成员变量的相互关系...很好的例子
【解决方案3】:

有两种方法。

要么使用“魔法”默认值:

void add(int key, node* curr = NULL)
{
    if (curr == NULL)
        curr = root;
    // ...
}

或完全放弃默认值并使用重载:

void add(int key, node* curr)
{
    // ...
}

void add(int key)
{
    add(key, root);
}

我个人的偏好是后者,但你根本不应该在树的界面中真正暴露节点类型,因为这会让树的用户破坏它的平衡。

【讨论】:

    【解决方案4】:

    这样使用: const node* root = NULL; void add(int key,node*curr=root);

    您可以在此处查看实际运行的示例: http://ideone.com/tJ1r29

    【讨论】:

    • hmm,如果根节点是 const,最终将无法在根节点的左侧或右侧添加另一个节点...
    猜你喜欢
    • 2015-01-15
    • 2017-11-21
    • 2017-03-12
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    • 1970-01-01
    • 2011-01-18
    相关资源
    最近更新 更多