在编写c++头文件后,还需要再.cpp文件里面复制一份非常的麻烦
找过了不少方法都很难实现
提供了一个python脚本帮助你实现这个过程
python
#!/usr/bin/env python3
import re
import sys
def process_class(content):
"""Extract and process the next class in the content, returning function definitions and remaining content."""
# Enhanced regex to match class definitions with virtual and multiple inheritance
class_match = re.search(r'class\s+(\w+)(?:\s*:\s*(?:virtual\s+)?(?:public\s+)?\w+(?:\s*,\s*(?:virtual\s+)?(?:public\s+)?\w+)*)?', content)
if not class_match:
return None, content
class_name = class_match.group(1)
# Find the start of the class definition, including the opening brace
class_start = re.search(rf'class\s+{class_name}\s*(?::\s*(?:virtual\s+)?(?:public\s+)?\w+(?:\s*,\s*(?:virtual\s+)?(?:public\s+)?\w+)*)?\s*{{', content)
if not class_start:
print(f"Error: Could not find class definition start for {class_name}")
return None, content
start_pos = class_start.end() - 1 # Position right before the opening brace
brace_count = 1
i = start_pos + 1
while i < len(content) and brace_count > 0:
if content[i] == '{':
brace_count += 1
elif content[i] == '}':
brace_count -= 1
i += 1
if brace_count != 0:
print(f"Error: Mismatched braces in class {class_name}")
return None, content
class_content = content[start_pos:i]
remaining_content = content[i:]
# Remove access modifiers
class_content = re.sub(r'^\s*(public|private|protected):\s*', '', class_content, flags=re.MULTILINE)
# Find function declarations (excluding constructors and destructors)
func_pattern = r'(friend\s+)?([\w:&<>]+\s*[\*&]?\s*)?(operator[\w<>=!+\-*]+)?\s*(\w+)?\s*\(([^)]*)\)\s*(const)?\s*(?!=)\s*;'
functions = re.findall(func_pattern, class_content, re.MULTILINE)
definitions = []
for func in functions:
friend, return_type, op_name, func_name, params, const = func
if not func_name and not op_name:
continue # Skip if no function name or operator
# Skip constructors and destructors
if func_name == class_name or (func_name and func_name.startswith('~')):
continue
# Clean params: remove default values
cleaned_params = []
for p in params.split(','):
p = p.strip()
if p:
p = re.sub(r'\s*=\s*[^,)]+', '', p)
cleaned_params.append(p)
params = ', '.join(cleaned_params)
# Clean return_type
return_type = return_type.strip() if return_type else ''
if not friend and return_type:
while return_type.startswith(('static ', 'virtual ', 'explicit ')):
return_type = return_type.split(' ', 1)[1].strip()
const = ' const' if const else ''
if op_name:
func_name = f'operator{op_name[len("operator"):]}'
if friend:
func_def = f"{return_type} {func_name}({params}){const} {{\n // TODO: Implement\n}}\n"
else:
func_def = f"{return_type} {class_name}::{func_name}({params}){const} {{\n // TODO: Implement\n}}\n"
definitions.append(func_def)
return definitions, remaining_content
def process_global_functions(content):
"""Extract and generate definitions for global functions without bodies."""
global_func_pattern = r'^\s*(?!class|struct)(\w+\s+)+(\w+)(\s*\([^;]*\))\s*;'
matches = re.finditer(global_func_pattern, content, re.MULTILINE)
definitions = []
for match in matches:
return_type = match.group(1).strip()
func_name = match.group(2).strip()
params = match.group(3).strip()
cleaned_params = []
for p in params[1:-1].split(','):
p = p.strip()
if p:
p = re.sub(r'\s*=\s*[^,)]+', '', p)
cleaned_params.append(p)
params = ', '.join(cleaned_params)
func_def = f"{return_type} {func_name}({params}) {{\n // TODO: Implement\n}}\n"
definitions.append(func_def)
return definitions
def process_header(input_file, output_file):
"""Process the header file and generate the corresponding .cpp file."""
try:
with open(input_file, 'r', encoding='utf-8') as f:
content = f.read()
except Exception as e:
print(f"Error: Could not read file {input_file}: {e}")
sys.exit(1)
function_definitions = []
while True:
defs, content = process_class(content)
if defs is None:
break
function_definitions.extend(defs)
global_defs = process_global_functions(content)
function_definitions.extend(global_defs)
try:
output = [f'#include "{input_file}"\n\n'] + function_definitions
with open(output_file, 'w', encoding='utf-8') as f:
f.writelines(output)
print(f"Successfully generated {output_file}!")
except Exception as e:
print(f"Error: Could not write to file {output_file}: {e}")
sys.exit(1)
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage: python3 script.py input.h [output.cpp]")
sys.exit(1)
input_path = sys.argv[1]
output_path = sys.argv[2] if len(sys.argv) >= 3 else input_path.replace('.h', '.cpp')
process_header(input_path, output_path)
这个脚本接收两个参数,第一个是你的头文件,第二个是输出的地址,可以不提供第二个地址,则默认以cpp结尾存储再当前目录
全局脚本调用
~/.local/bin
是用户专属的可执行文件目录,推荐用于全局调用。
查看是否存在,不存在则手动创建一下
python
mkdir -p ~/.local/bin
然后把python脚本放到这个目录下
注意看一下是否有执行权限
没有的话添加一下
python
chmod +x ~/.local/bin/generate_cpp.py
然后需要配置环境变量
查看当前环境
python
echo $PATH
查看这个目录是否在环境下
不在的话我们添加一下
python
vim ~/.bashrc
把下面这个添加到最后一行
python
export PATH="$HOME/.local/bin:$PATH"
再重启一下
python
source ~/.bashrc
你就可以看到了
然后我们就能全局调用这个脚本
测试示例

cpp
#pragma once
#include <iostream>
class Stonewt
{
public:
enum Mode { STONE, POUND, INT };
private:
enum { Lbs_per_stn = 14 };
int stone;
double pds_left;
double pounds;
Mode mode;
public:
Stonewt(double lbs, Mode form = STONE);
Stonewt(int stn, double lbs, Mode form = STONE);
Stonewt()
{
stone = pounds = pds_left = 0;
mode = STONE;
}
void stoneMode() { mode = STONE; }
void poundMode() { mode = POUND; }
void intMode() { mode = INT; }
~Stonewt(){};
bool operator<(const Stonewt &s);
bool operator>(const Stonewt &s);
bool operator<=(const Stonewt &s);
bool operator>=(const Stonewt &s);
bool operator==(const Stonewt &s);
bool operator!=(const Stonewt &s);
Stonewt operator+(const Stonewt &s);
Stonewt operator-(const Stonewt &s);
Stonewt operator-();
friend Stonewt operator*(const Stonewt &s1, const Stonewt &s2);
friend std::ostream &operator<<(std::ostream &os, const Stonewt &);
friend std::istream &operator>>(std::istream &os, Stonewt &);
};
class test:Stonewt{
public:
void fun1();
virtual void fun2() const;
static void fun3();
};
void show(const Stonewt & st);
void func();
测试示例来自c++Primerplus编程练习第11章第6题
这是生成的stonewt.cpp
文件
cpp
#include "stonewt.h"
✹ Stonewt::Stonewt(double lbs, Mode form) {
}
✹ Stonewt::Stonewt(int stn, double lbs, Mode form) {
}
✹ bool Stonewt::operator<(const Stonewt &s) {
✹ }
✹ bool Stonewt::operator>(const Stonewt &s) {
✹ }
✹ bool Stonewt::operator<=(const Stonewt &s) {
✹ }
✹ bool Stonewt::operator>=(const Stonewt &s) {
✹ }
✹ bool Stonewt::operator==(const Stonewt &s) {
✹ }
✹ bool Stonewt::operator!=(const Stonewt &s) {
✹ }
✹ Stonewt Stonewt::operator+(const Stonewt &s) {
✹ }
✹ Stonewt Stonewt::operator-(const Stonewt &s) {
✹ }
Stonewt Stonewt::operator-() {
✹ }
✹ Stonewt operator*(const Stonewt &s1, const Stonewt &s2) {
✹ }
✹ std::ostream & operator<<(std::ostream &os, const Stonewt &) {
✹ }
✹ std::istream & operator>>(std::istream &os, Stonewt &) {
✹ }
void test::fun1() {
}
void test::fun2() const {
}
void test::fun3() {
}
✹ void show(const Stonewt & st) {
}
void func() {
}
这些✹
是vim的提示,实际上没有
vim中调用
注意要完成前面的全局配置
推荐安装vimplus,可以参考这里
cpp
:!generate_cpp.py % %.cpp
可以直接用这个调用,可以省略%.cpp
配置快捷键
添加我们自己的配置
cpp
vim ~/.vimrc.custom.config
在其中添加这样的内容,你就可以使用,cpp
来生成源文件了
cpp
function! GenerateCpp()
write
let output = system('generate_cpp.py ' . expand('%') . ' ' . expand('%:r') . '.cpp')
if v:shell_error
copen
caddexpr output
echo "Error generating " . expand('%:r') . ".cpp"
else
echo "Generated " . expand('%:r') . ".cpp successfully!"
endif
endfunction
autocmd FileType cpp,h nnoremap <silent> <leader>cpp :call GenerateCpp()<CR>