我有一个用C编写的.inc文件。它包含一些带有实现的定义和方法签名。
.inc文件:
#define CONCAT(x,y) x ## y
#define LCONCAT(x,y) CONCAT(x,y)
#define DLIST LCONCAT(LCONCAT(double_,LISTELEMENT),_list)
#define DELETEDFIRST LCONCAT(delete_first_double_,LISTELEMENT)
int DELETEDFIRST (DLIST **first, DLIST **last);
int DELETEDFIRST (DLIST **first, DLIST **last)
{...}
我想把它带到c ++。在我的.h文件中,我有define指令和方法签名(封装在命名空间中)。在.cpp中,我只有方法实现。
.h文件
#define CONCAT(x,y) x ## y
#define LCONCAT(x,y) CONCAT(x,y)
#define DLIST LCONCAT(LCONCAT(double_,LISTELEMENT),_list)
#define DELETEDFIRST LCONCAT(delete_first_double_,LISTELEMENT)
namespace ListFunctions {
int DELETEDFIRST (DLIST **first, DLIST **last);
}
.cpp文件
# include ListFunctions.h
namespace ListFunctions {
int DELETEDFIRST (DLIST **first, DLIST **last) {...}
}
我打算在开发我的模块时使用这些列表函数。在我的module.h中,我定义了一个类型 double_ 节点 _list (双端),在我的module.cpp中,我将LISTELEMENT定义为“ node “然后包含ListFunctions.h。但ListFunctions.cpp中的相同内容会导致编译错误:
..\ListFunctions.h(86): error C2065:'double_LISTELEMENT_list' : undeclared identifier
..\ListFunctions.h(86): error C2065: 'first' : undeclared identifier
..\ListFunctions.h(86): error C2065: 'double_LISTELEMENT_list' : undeclared identifier
..\ListFunctions.h(86): error C2065: 'last' : undeclared identifier
..\ListFunctions.h(86): error C2078: too many initializers
后来我想把c风格的实现翻译成c ++。由于我缺乏经验,我想知道其他人是否同意我在做什么。
答案 0 :(得分:9)
停止。很明显你知道C,但你不懂C ++。 在尝试使用它编写代码之前学习C ++。这是一种与C语言明显不同的语言,并且尝试编写C ++就好像它是“C with stuff”一样会导致代码错误。
首先:你想要的几乎肯定是带有方法的C ++ class
,而不是包含对数据类型(可能是结构?)进行操作的函数的命名空间。
第二:我不确定你在这里定义的所有宏到底是做什么的,但它看起来好像你试图定义一组变量函数。这个概念已经作为模板存在于C ++中。不要试图用宏复制它;你会混淆那些阅读你代码的人。
答案 1 :(得分:2)
对于特定的问题,C和C ++都无效,两者都应该调用该错误。解决方案是将这一行放在函数之前,告诉编译器稍后将定义此结构,但是现在我们需要指针或引用它。
struct DLIST;
但是,您遇到的主要问题是您的目标似乎是将函数定义放在cpp文件中。不幸的是,在C和C ++中不能以通用方式干净地完成。问题是您希望能够为各种类型(通过模板或宏)专门化List,但是当您编译该cpp文件本身时,它无法知道要为列表专门化的类型。对于C和C ++中的通用结构,通常定义仍然必须在某种标题或包含文件中。
有一种替代方案,可以让你将函数定义放入cpp文件中,但它非常奇怪,我不推荐它:
list_declarations.hpp
template<class LISTELEMENT>
class double_list {
typedef LISTELEMENT value_type;
struct iterator {
...iterator stuff
};
static int DELETEDFIRST (iterator first, iterator last);
};
extern template class double_list<int>; //declare int specialization
extern template class double_list<char>; //declare char specialization
list_definitions.cpp:
#include "list_declarations.h"
template<class LISTELEMENT>
int double_list<LISTELEMENT>::DELETEDFIRST(
double_list<LISTELEMENT>::iterator first,
double_list<LISTELEMENT>::iterator last)
{
...implementation
}
template class double_list<int>; //define int specialization
template class double_list<char>; //define char specialization
//note that all of these _must_ be in the same file as the function definitions
在C ++中制作通用列表的常规方法是模糊的:
#pragma once
template<class LISTELEMENT, class allocator=std::allocator<LISTELEMENT>>
class double_list {
public:
typedef allocator allocator_type;
typedef typename allocator::value_type value_type;
typedef typename allocator::reference reference;
typedef typename allocator::const_reference const_reference;
typedef typename allocator::difference_type difference_type;
typedef typename allocator::size_type size_type;
class iterator {
DLIST * current;
explicit iterator(DLIST* c);
public:
typedef LISTELEMENT value_type;
typedef LISTELEMENT& reference;
typedef LISTELEMENT* pointer;
typedef std::ptrdif_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
iterator();
iterator& operator++(); //prefix increment
iterator operator++(int); //postfix increment
iterator& operator--(); //prefix decrement
iterator operator--(int); //postfix decrement
reference operator*() const;
pointer operator->() const;
friend bool operator==(const iterator&, const iterator&);
friend bool operator!=(const iterator&, const iterator&);
friend void swap(iterator& lhs, iterator& rhs);
};
class const_iterator {
const DLIST * current;
explicit iterator(const DLIST* c);
public:
const_iterator(iterator c);
...see above
};
double_list();
double_list(const double_list& rhs);
~double_list();
double_list& operator=(const double_list& rhs);
int delete_first(iterator first, iterator last);
private:
pointer first;
pointer last;
};
加上Writing your own STL Container中感兴趣的任何其他成员。由于它是模板类,因此所有函数定义都必须位于标题中。显然,这与