注册 登录
编程论坛 C++教室

C++静态成员的编译 error LNK2001: 无法解析的外部符号 "private: static int AddressBook::m_s_i

云飞aini 发布于 2011-09-27 20:08, 11713 次点击
程序代码:
//编的一个简单的通讯录的类 对静态成员的运用编译总是报错
class AddressBook
{
public:
    AddressBook(string aName = "NULL",int aPhonenum = 0);
    ~AddressBook();
    static int getLength();
    static void addLength();
    static void decLength();
    void setName(string aName);
    string getName();
    void setPhonenum(int aPhonenum);
    int getPhonenum();
private:
    string m_strName;
    int    m_iPhonenum;
    static int m_s_ilength;
};
AddressBook::AddressBook(string aName /* = "NULL" */,int aPhonenum /* = 0 */)
{
    m_strName = aName;
    m_iPhonenum = aPhonenum;
}
AddressBook::~AddressBook()
{
    --m_s_ilength;
}
错误是AddressBook.obj : error LNK2001: 无法解析的外部符号 "private: static int AddressBook::m_s_ilength" (?m_s_ilength@AddressBook@@0HA)
求解
6 回复
#2
lintaoyn2011-09-27 20:37
类里的叫声名
下面这句叫定义
int AddressBook::m_s_ilength = 0;
#3
云飞aini2011-09-27 21:31
回复 2楼 lintaoyn
后边那个析构函数有错吗?我删了它就不报错了,不知道为什么
#4
lintaoyn2011-09-27 22:03
析构函数做一些扫尾的事,你不写编译器也会替你生成一个,但是你声明之后得有定义。我记得在继承的时候好像有注意的地方,具体记不清了
#5
城东古桥2011-09-27 23:07
回复 3楼 云飞aini
因为你在拆构函数中调用了静态变量m_s_ilength,所以m_s_ilength必须初始化。

[ 本帖最后由 城东古桥 于 2011-10-1 22:45 编辑 ]
#6
SeekProDream2011-09-28 04:33
类中的static类型变量必须要类定义的头文件对应的.cpp文件中定义, int AddressBook:: m_s_ilength = 0(这里按照你要求的值来赋)。因为你的析构函数中用到这个变量,所以在链接时会发现这个符号无法解析。如果你删了析构函数,整个过程中这个static无定义的变量没被用到,所以没报错。
还有4楼说的析构函数在有继承时重要的地方,也就是一定要把析构函数设为virtual,这个只要在最基层的类中设就行,后面自动地动态绑定。因为在有继承时,每个类的析构函数只负责删除该类独有的部分,它继承的部分无法靠它来删除,而且对象在析构过程中类型会变化,正好利用多态性来一层一层来删除,最后整个对象所有部分全部析构。
比如:A继承B,B继承C,C继承D, 对于A类型的对象a,运行析构函数时,由于多态,执行的是A的析构函数,A的部分析构完时对象类型变成B,继续析构时由于多态会执行B的析构函数,同理,最后会执行D的析构函数,直到结束,整个a对象全部析构。
这些只是个人的一点理解。
#7
lqsh2011-09-29 20:48
程序代码:
int n=0;
int m=0;
class AddressBook
{
public:
    AddressBook(string aName = "NULL",int aPhonenum = 0);
    ~AddressBook();
    static int getLength();
    static void addLength(AddressBook &a);
    static void decLength();
    void setName(string aName);
    string getName();
    void setPhonenum(int aPhonenum);
    int getPhonenum();
private:
    string m_strName;
    int    m_iPhonenum;
    static int m_s_ilength;
};

void AddressBook::addLength(AddressBook &a)
{
    m_s_ilength++;
    a.m_iPhonenum++;

}

int AddressBook::getLength()
{
    cout<<&m_s_ilength<<endl;
    return m_s_ilength;

}

int AddressBook::m_s_ilength=0;
AddressBook::AddressBook(string aName /* = "NULL" */,int aPhonenum /* = 0 */)
{
    m_strName = aName;
    m_iPhonenum = aPhonenum;
}
AddressBook::~AddressBook()
{
    --m_s_ilength;
}

int main()
{
    AddressBook a;
    a.addLength(a);
    cout<<&n<<"  "<<&m<<endl;

    cout<<AddressBook::getLength()<<endl;

    return 0;
}
静态成员分析:
静态类成员包括静态成员函数和静态成员数据,静态数据成员属于类域内的全局变量,属于整个类共有,不属于特定的对象,必要在类外进行初始化。
静态成员一样服从访问权限,私有有静态成员只能在类内部访问,公有或者保护能在类外通过类名或对象名访问,
静态成员函数可以直接引用类名静态成员,但不能直接引用非静态成员。
验证类域内的全局变量 ,全局变量存在堆中,数据按声明顺序递增存储
    &n 地址为0X0108C1A0(H)
    &m地址为0X0108C1A4(H)
    &m_s_ilength地址为0X0108C1A8(H)
1