命名空间中派生类的前向声明问题

时间:2022-01-26 17:53:01
现有类层次如下

//////////////////////////////////
a.h文件:-----------

class A
{
.....
A(){ ; }
};

//////////////////////////////////
b.h文件-----------

#include "a.h"

namespace  SP
{  
class B : public A
 {
..........
B(){ ; }
}; 
}

/////////////////////////////////////
c.h文件-----------

#include "a.h"

namespace  SP
{
    class B;//前向声明class B 
}

void fun1(SP::B * pb);
void fun2( A * pa);

/////////////////////////////////
c.cpp文件
#include "c.h"

void fun1(SP::B * pb);
{
     fun2(pb);   //编译错误:error C2664: “fun2”: 不能将参数 1 从“SP::B * ”转换为“ A * ” 与指向的类型无关;
....................
}

void fun2( A * pa)
{
.........
}

/////////////////////////////////
main.cpp文件
#include "a.h"
#include "b.h"
#include "c.h"
............................

在命名空间中的类从继承于外部类,并进行前向声明,在运行代码中无法将派生类SP::B指针转换为基类A的指针。如果把SP::B类的全部头文件c.h文件包含,就可以编译通过。
问题是:不包含头文件,只前向声明,如何实现?

10 个解决方案

#1


struct A {} ;

struct B ;

void func2 (A &a) {

}

void func1 (B &) ;

struct B :public A {} ;

void func1 (B &a) {
func2 (a) ;
}

#2


仅有前置声明,看不到定义,那编译器如何知道B* 可以隐式装换为 A*?那你函数中也用不了它们的成员了啊

你试试强制转换fun2((A*)pb);

#3


引用 1 楼 ID870177103 的回复:
struct A {} ;

struct B ;

void func2 (A &a) {

}

void func1 (B &) ;

struct B :public A {} ;

void func1 (B &a) {
func2 (a) ;
}


你这样派生当然没有问题,你把
struct B :public A {} ;放到自己定义的命名空间中试试?你没看清我的问题:在命名空间中的类从继承于外部类,。。。。。。。

#4


在命名空间中的类从继承于外部类
    
namespace  SP
{  
class B : public A
 {
..........
B(){ ; }
}; 
}
 

前向声明出现编译错误:B* 无法转换为A*

#5


struct A {} ;

namespace F {
struct B ;
} ;

void func2 (A &a) {

}

void func1 (F::B &) ;

namespace F {
struct B :public A {} ;
} ;

void func1 (F::B &a) {
func2 (a) ;
}

#6


引用 5 楼 ID870177103 的回复:
struct A {} ;

namespace F {
struct B ;
} ;

void func2 (A &a) {

}

void func1 (F::B &) ;

namespace F {
struct B :public A {} ;
} ;

void func1 (F::B &a) {
func2 (a) ;
}


你的这个方式,编译不能通过,错误类同上B & 无法转换为A &

#7


VS和G++都能接受这段代码

#8



class A;
namespace ns
{
class B;
}
void fun2(A *pa);
void fun1(ns::B *pb);

int 
main(int argc, char ** argv) 
{
ns::B b;
fun1(&b);
}


void fun2(A *pa)
{

}

void fun1(ns::B *pb)
{
fun2(pb);
}

class A
{
A();
};

namespace ns
{
class B : public A
{
public:
B();
};

}

编译结果如下:1>f:\编程\vs2012\consoleapplication1\consoleapplication1\consoleapplication1.cpp(492): error C2079: “b”使用未定义的 class“ns::B”
1>f:\编程\vs2012\consoleapplication1\consoleapplication1\consoleapplication1.cpp(493): error C2664: “fun1”: 不能将参数 1 从“int *”转换为“ns::B *”
1>          与指向的类型无关;转换要求 reinterpret_cast、C 样式转换或函数样式转换
1>f:\编程\vs2012\consoleapplication1\consoleapplication1\consoleapplication1.cpp(504): error C2664: “fun2”: 不能将参数 1 从“ns::B *”转换为“A *”
1>          与指向的类型无关;转换要求 reinterpret_cast、C 样式转换或函数样式转换
========== 全部重新生成: 成功 0 个,失败 1 个,跳过 0 个 ==========

#9


class A;
namespace ns
{
class  B;
}
void fun2(A & a);
void fun1(ns::B & b);


void fun2(A & a)
{

}

void fun1(ns::B & b)
{
fun2(b);
}

class A
{
A();
};

namespace ns
{
class B : public A
{
public:
B();
};

}

int 
main(int argc, char ** argv) 
{
ns::B  b;
fun1( b );
}

以上代码编译:1>------ 已启动全部重新生成: 项目: ConsoleApplication1, 配置: Debug Win32 ------
1>  stdafx.cpp
1>  ConsoleApplication1.cpp
1>f:\编程\vs2012\consoleapplication1\consoleapplication1\consoleapplication1.cpp(498): error C2664: “fun2”: 不能将参数 1 从“ns::B”转换为“A &”
========== 全部重新生成: 成功 0 个,失败 1 个,跳过 0 个 ==========

#10


class A;
namespace ns
{
class  B;
}
void fun2(A & a);
void fun1(ns::B & b);

void fun4(A * pa);
void fun3(ns::B *pb);


void fun2(A & a)


}

void fun1(ns::B & b)
{
fun2( b );
}

void fun4(A * pa)


}

void fun3(ns::B * pb)
{
fun4( pb );
}


class A
{
public:
A(){ ; }
};

namespace ns
{

class B : public A
{
public:
B(){ ; }
};

}

int 
main(int argc, char ** argv) 
{
ns::B  b;
fun1( b );

fun3( &b );

}

------ 已启动全部重新生成: 项目: ConsoleApplication1, 配置: Debug Win32 ------
1>  stdafx.cpp
1>  ConsoleApplication1.cpp
1>f:\编程\vs2012\consoleapplication1\consoleapplication1\consoleapplication1.cpp(501): error C2664: “fun2”: 不能将参数 1 从“ns::B”转换为“A &”
1>f:\编程\vs2012\consoleapplication1\consoleapplication1\consoleapplication1.cpp(511): error C2664: “fun4”: 不能将参数 1 从“ns::B *”转换为“A *”
1>          与指向的类型无关;转换要求 reinterpret_cast、C 样式转换或函数样式转换
========== 全部重新生成: 成功 0 个,失败 1 个,跳过 0 个 ==========

#1


struct A {} ;

struct B ;

void func2 (A &a) {

}

void func1 (B &) ;

struct B :public A {} ;

void func1 (B &a) {
func2 (a) ;
}

#2


仅有前置声明,看不到定义,那编译器如何知道B* 可以隐式装换为 A*?那你函数中也用不了它们的成员了啊

你试试强制转换fun2((A*)pb);

#3


引用 1 楼 ID870177103 的回复:
struct A {} ;

struct B ;

void func2 (A &a) {

}

void func1 (B &) ;

struct B :public A {} ;

void func1 (B &a) {
func2 (a) ;
}


你这样派生当然没有问题,你把
struct B :public A {} ;放到自己定义的命名空间中试试?你没看清我的问题:在命名空间中的类从继承于外部类,。。。。。。。

#4


在命名空间中的类从继承于外部类
    
namespace  SP
{  
class B : public A
 {
..........
B(){ ; }
}; 
}
 

前向声明出现编译错误:B* 无法转换为A*

#5


struct A {} ;

namespace F {
struct B ;
} ;

void func2 (A &a) {

}

void func1 (F::B &) ;

namespace F {
struct B :public A {} ;
} ;

void func1 (F::B &a) {
func2 (a) ;
}

#6


引用 5 楼 ID870177103 的回复:
struct A {} ;

namespace F {
struct B ;
} ;

void func2 (A &a) {

}

void func1 (F::B &) ;

namespace F {
struct B :public A {} ;
} ;

void func1 (F::B &a) {
func2 (a) ;
}


你的这个方式,编译不能通过,错误类同上B & 无法转换为A &

#7


VS和G++都能接受这段代码

#8



class A;
namespace ns
{
class B;
}
void fun2(A *pa);
void fun1(ns::B *pb);

int 
main(int argc, char ** argv) 
{
ns::B b;
fun1(&b);
}


void fun2(A *pa)
{

}

void fun1(ns::B *pb)
{
fun2(pb);
}

class A
{
A();
};

namespace ns
{
class B : public A
{
public:
B();
};

}

编译结果如下:1>f:\编程\vs2012\consoleapplication1\consoleapplication1\consoleapplication1.cpp(492): error C2079: “b”使用未定义的 class“ns::B”
1>f:\编程\vs2012\consoleapplication1\consoleapplication1\consoleapplication1.cpp(493): error C2664: “fun1”: 不能将参数 1 从“int *”转换为“ns::B *”
1>          与指向的类型无关;转换要求 reinterpret_cast、C 样式转换或函数样式转换
1>f:\编程\vs2012\consoleapplication1\consoleapplication1\consoleapplication1.cpp(504): error C2664: “fun2”: 不能将参数 1 从“ns::B *”转换为“A *”
1>          与指向的类型无关;转换要求 reinterpret_cast、C 样式转换或函数样式转换
========== 全部重新生成: 成功 0 个,失败 1 个,跳过 0 个 ==========

#9


class A;
namespace ns
{
class  B;
}
void fun2(A & a);
void fun1(ns::B & b);


void fun2(A & a)
{

}

void fun1(ns::B & b)
{
fun2(b);
}

class A
{
A();
};

namespace ns
{
class B : public A
{
public:
B();
};

}

int 
main(int argc, char ** argv) 
{
ns::B  b;
fun1( b );
}

以上代码编译:1>------ 已启动全部重新生成: 项目: ConsoleApplication1, 配置: Debug Win32 ------
1>  stdafx.cpp
1>  ConsoleApplication1.cpp
1>f:\编程\vs2012\consoleapplication1\consoleapplication1\consoleapplication1.cpp(498): error C2664: “fun2”: 不能将参数 1 从“ns::B”转换为“A &”
========== 全部重新生成: 成功 0 个,失败 1 个,跳过 0 个 ==========

#10


class A;
namespace ns
{
class  B;
}
void fun2(A & a);
void fun1(ns::B & b);

void fun4(A * pa);
void fun3(ns::B *pb);


void fun2(A & a)


}

void fun1(ns::B & b)
{
fun2( b );
}

void fun4(A * pa)


}

void fun3(ns::B * pb)
{
fun4( pb );
}


class A
{
public:
A(){ ; }
};

namespace ns
{

class B : public A
{
public:
B(){ ; }
};

}

int 
main(int argc, char ** argv) 
{
ns::B  b;
fun1( b );

fun3( &b );

}

------ 已启动全部重新生成: 项目: ConsoleApplication1, 配置: Debug Win32 ------
1>  stdafx.cpp
1>  ConsoleApplication1.cpp
1>f:\编程\vs2012\consoleapplication1\consoleapplication1\consoleapplication1.cpp(501): error C2664: “fun2”: 不能将参数 1 从“ns::B”转换为“A &”
1>f:\编程\vs2012\consoleapplication1\consoleapplication1\consoleapplication1.cpp(511): error C2664: “fun4”: 不能将参数 1 从“ns::B *”转换为“A *”
1>          与指向的类型无关;转换要求 reinterpret_cast、C 样式转换或函数样式转换
========== 全部重新生成: 成功 0 个,失败 1 个,跳过 0 个 ==========