我有一个问题,理解一些C++语法结合函数指针和函数声明,即:
通常当我们想要声明一种类型的函数时,我们会做如下:
typedef void(*functionPtr)(int);
Run Code Online (Sandbox Code Playgroud)
这对我来说没问题.从现在开始,functionPtr是一个类型,它表示指向函数的指针,它返回void并以值作为参数获取int.
我们可以使用它如下:
typedef void(*functionPtr)(int);
void function(int a){
std::cout << a << std::endl;
}
int main() {
functionPtr fun = function;
fun(5);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我们5
打印在屏幕上.
我们有指向函数的指针fun
,我们为函数分配了一些现有的指针 - function
我们通过指针执行这个函数.凉.
现在正如我在一些书中读到的那样,函数和指向函数的方法在某种程度上是相同的,所以事实上在function()
每次声明函数声明函数后我们指的是真正的函数和指向同一类型函数的指针,所以下面的编译和每个指令给出相同的结果(5在屏幕上打印):
int main() {
functionPtr fun = function;
fun(5);
(*fun)(5);
(*function)(5);
function(5);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
所以现在只要我能想象,那些指向函数和函数的指针几乎是一样的,那么它对我来说就好了.
然后我,如果指向函数和实函数的指针是相同的,那么为什么我不能做以下事情:
typedef void(functionPtr)(int); //removed *
void function(int a){
std::cout << a << std::endl;
}
int main() {
functionPtr fun = function;
fun(5);
return 0;
} …
Run Code Online (Sandbox Code Playgroud) 因此,通常枚举用于将"常量整数"组声明为另一种类型,代表某种东西.例如.
enum Color {RED=0, BLUE, YELLOW};
Run Code Online (Sandbox Code Playgroud)
这很清楚.但最近我在代码中遇到了以下内容.这是嵌入式系统的编译器.
enum State {DISABLED=0, ENABLED=!DISABLED};
Run Code Online (Sandbox Code Playgroud)
它运作得很好.它表现为布尔类型.我的问题是,它(这种语法)是否符合ANSI标准?
如果它符合标准,那么为什么编译器会在内部定义像_Bool这样的布尔表示,然后在stdbool.h
(对于C语言)它们:
#define bool _Bool
... // here goes definitions of true and false
Run Code Online (Sandbox Code Playgroud)
代替
enum bool {false=0, true=!false};
Run Code Online (Sandbox Code Playgroud)
哪个更干净?
正如问题所述,我知道在C++ 17中会有名称空间和枚举器的属性.这将如何影响我们的代码?这些属性是什么以及它们允许我们做什么?我找不到任何理解这个新功能的好资源.
您好我想知道为什么C++标准允许我们在嵌套类中访问外部类的私有字段,而它禁止从外部类访问内部类的私有字段.我明白了,这个例子:
class OuterClass{
public:
class InnerClass{
public:
void printOuterClass(OuterClass& outer) {cout << outer.m_dataToDisplay;};
};
private:
int m_dataToDisplay;
};
Run Code Online (Sandbox Code Playgroud)
很好,因为内心,有时可能会很复杂.但我认为以下情况也很好:
class Algorithm{
public:
class AlgorithmResults{
public:
void readAlgorithmResult();
private:
void writeAlgorithmResult();
};
void calculate(AlgorithmResults& results, Arguments...){
//calculate stuff
results.writeAlgorithmResult(results);
}
};
Run Code Online (Sandbox Code Playgroud)
对我来说,这种结构非常有意义,尽管在C++中是不允许的.我也注意到,有一段时间两者都被Java所允许,但现在第二个例子也被禁止了.是什么原因,第一个例子被允许而另一个被拒绝?
简单来说,我有一个简单的指针:
int* a;
Run Code Online (Sandbox Code Playgroud)
现在,我想改变这个指针的值.我想在一个函数中这样做.函数确保它不会改变指针指向的对象,但会改变指针本身.这就是为什么我希望这个函数接受如下参数:非const引用(因为指针的值将被改变)到指向const对象的非const指针(指针本身可以改变)(函数保证,该对象,指针指向不会被改变).
最简单的功能是:
void function(const int*& a){
a = 0;
}
Run Code Online (Sandbox Code Playgroud)
但是当我尝试调用此函数时:
int main(){
int* a;
function(a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译器不满意并说:
从'const int*'函数(a)的rvalue初始化'const int*&'类型的非const引用;
我不太明白这个错误,因为对我来说没有涉及rvalue(我传递对象的引用,已经存在于堆栈中.)
问题是,我该怎么做呢?
可以在此处找到示例:https://ideone.com/D45Cid
编辑:
有人建议,我的问题是为什么将"指向非const的指针"转换为"指向const的指针"是不合法的.
我的问题是不同的,因为我没有使用指针指针我只使用指向对象/值的指针并存储对它的引用,因此情况就像在回答这个问题:
const char c = 'c';
char* pc;
const char** pcc = &pc; // not allowed
*pcc = &c;
*pc = 'C'; // would allow to modify a const object
Run Code Online (Sandbox Code Playgroud)
在我的情况下是不可能的,因为我无法取消引用顶级指针(我没有这样的指针).
此外,我质疑这个问题的完美和干净的解决方案,这个问题没有涉及
在Scott Meyer的书"Effective Modern C++"中,我们可以读到:
std::vector<bool> features(const Widget& w);
Widget w;
…
bool highPriority = features(w)[5];
…
processWidget(w, highPriority);
Run Code Online (Sandbox Code Playgroud)
以及auto的选项
auto highPriority = features(w)[5];
Run Code Online (Sandbox Code Playgroud)
这会导致未定义的行为,因为features()
返回的事实是std::vector<bool>
,std::vector<bool>::reference
在返回值时使用类型的代理对象opearator[]
.
作为解决方案,建议不要停止使用auto
,而是使用static_casts
.
所以Scott Meyers建议使用:
auto highPriority = static_cast<bool>(features(w)[5]);
Run Code Online (Sandbox Code Playgroud)
代替:
bool highPriority = features(w)[5];
Run Code Online (Sandbox Code Playgroud)
我的问题是:这两者之间有什么真正的区别?在我看来两者都是相同的,因为这两种方法都以完全相同的方式使重构变得更难(在函数功能中改变返回值类型不会使变量highPriority成为不同类型)而第二种方法更短.
因此,我是一名电工和程序员,我认为我非常了解FSM设计模式.它是:
Nodes
,Node
当程序在此节点中时,每个人都知道该做什么,Node
contains references to another chosen nodes
知道在什么条件下,他应该继续选择一个.event
或after processing
节点,Node proceeds
到下一个选择的节点我想,这对我来说很清楚.虽然最近,当我实施一台国家机器时,一个人告诉我,事实上它有点修改了责任链(不确定他是否正确),而且我做了/做了什么:
Nodes
(未表示线性或树形结构)不幸的是,我担心,由于法律问题,我不允许在这里粘贴类图.
另一方面,我们有责任链,我(按照我的理解)以下列方式定义,即:
ItemToProcess
接口,Node
接口,ItemToProcess
并转发处理过的一个节点nextNode
据我所知:
Chain Of Responsibility
,我们想要一个被处理的项目(或至少试图要处理)的每个节点StateMachine
用来表示图表StateMachine
用来执行计算,计算的顺序或种类可能因某些事件而异.我想请你确认我对这些设计模式的理解,或者告诉我在理解上的错误.
所以假设我有一个包含函数对象的类,并且在构造函数调用中我传递参数,这些参数将在稍后传递给函数对象.就像是:
class Binder{
public:
Binder(functional_object, listOfParameters);
callFunctionalObject(); // calls functional object with given list of parameters
};
Run Code Online (Sandbox Code Playgroud)
在C++ 11之前,我无法使用Variadic模板,因此可以这样做:
struct none{};
template <typename T1, typename T2=none, typename T3=none>
class Binder{
public:
Binder(T1 functionalObject, T2 arg1=none(), T3arg3=none());
void callFunctionalObject();
private:
T1 m_functionalObject;
T2 m_arg1;
T3 m_arg2;
};
Run Code Online (Sandbox Code Playgroud)
哪里callFunctionalobject
可以实施如下:
template<typename T1, typename T2, typename T3>
void Binder<T1,T2,T3>::callFunctionalObject(){
callImpl(m_functionalObject, m_arg1, m_arg2);
}
Run Code Online (Sandbox Code Playgroud)
并且callImpl
会重载以识别类型的对象none
以将适当数量的参数传递给功能对象.
现在切换到C++ 11我不知道如何实现这个事实,在私有部分我有成员,我可以直接访问.
任何人都可以解释我使用C++ 11或C++ 14的方式吗?
我想用另一个使用rvalue构造一个对象.
class BigDataClass{
public:
BigDataClass(); //some default BigData
BigDataClass(BigDataClass&& anotherBigData);
private:
BigDataClass(BigDataClass& anotherBigData);
BigDataPtr m_data;
};
Run Code Online (Sandbox Code Playgroud)
所以现在我想做一些事情:
BigDataClass someData;
BigDataClass anotherData(std::move(someData));
Run Code Online (Sandbox Code Playgroud)
所以现在anotherData获得了rValue.事实上,这是一个eXpiring Value,因此http://en.cppreference.com/w/cpp/utility/move状态编译器现在有机会通过将someData移动到另一个来优化anotherData的初始化.
在我看来,我们实际上可以得到两件不同的东西:
我们真的可以获得如此未经优化的数据初始化方式吗?
以一种非常简单的方式.我们有以下代码:
struct templateTest{
struct {}m_none;
template <typename T1, typename T2, typename T3, typename T4>
templateTest(T1 arg1, T2 arg2=m_none, T3 arg3=m_none, T4 arg4=m_none){
}
};
struct nonTemplate{
nonTemplate(int arg1, int arg2=2, int arg3=3){}
};
int main()
{
nonTemplate(5);
nonTemplate(5,10);
templateTest test2(5,10);
templateTest test1(5);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我想要的是模板类中的默认构造函数参数.
默认参数与nonTemplate
类完全匹配,但它与templateTest
类型不同.我遇到的错误如下:
C2660:'templateTest :: templateTest':函数不带2个参数
用2个参数调用的构造函数
对于使用一个参数调用的构造函数,编译器想要调用copyConstructor,输出如下:
C2664:'templateTest :: templateTest(const templateTest&)':无法将参数1从'int'转换为'const templateTest&'
有没有办法在旧的C++编译器上实现我想要的东西,比如msvc 2011?
我的问题如下:
我正在尝试编写嵌入式应用程序,该应用程序必须提供它自己的链接程序脚本(使用arm-none-eabi-gcc编译器/链接器)。
嵌入式Bootloader加载二进制文件并从0x8000地址开始,这就是为什么我需要专用的链接描述文件的原因,该脚本允许我将所需的启动函数放入该地址。脚本代码如下:
MEMORY
{
ram : ORIGIN = 0x8000, LENGTH = 0x1000
}
SECTIONS
{
.start : { *(.start) } > ram
.text : { *(.text*) } > ram
.bss : { *(.bss*) } > ram
}
Run Code Online (Sandbox Code Playgroud)
现在,我要做的就是拥有一个函数,该函数将插入.start部分,因此它位于0x8000的开头。为此,我在库中使用以下功能:
__attribute__((section(".start"))) void notmain() {
main();
}
Run Code Online (Sandbox Code Playgroud)
这似乎工作正常,但是后来我将此库与带有函数notmain
的项目链接,该项目定义了main()
函数。在链接过程中,我看不到该.start
部分不再存在,并且notmain
符号完全丢失。当我将非主要功能移出库(移入项目)后,一切都很好。
我的理解是,链接器看到了,我的应用程序中根本没有使用.start节,这使它跳过了所有节。我已经尝试过为功能notmain添加一些属性,例如(__attribute__((used)) __attribute__((externally_visible))
),但是它也没有起作用(最终的二进制文件中notmain仍然缺少)。
CMake的源代码如下:
**专案**
project(AutomaticsControlExample)
enable_language(ASM)
set(CMAKE_CXX_STANDARD 14)
set(SOURCES main.cpp PID.hpp)
set(DEPENDENCIES RPIRuntime PiOS)
add_executable(${PROJECT_NAME} ${SOURCES})
target_link_libraries(${PROJECT_NAME} ${DEPENDENCIES})
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_OBJDUMP} -D …
Run Code Online (Sandbox Code Playgroud) 我感兴趣的是,标准是否会bool
在将类型转换为integer
类型后对类型类型的可能值进行说明。
例如下面的代码:
#include <iostream>
using namespace std;
int main() {
bool someValue=false;
*((int*)(&someValue)) = 50;
cout << someValue << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
打印 1,即使它被迫存储值 50。标准是否指定了任何相关内容?或者编译器是否为 bool 类型生成某种方法,如下所示:
operator int(){
return myValue !=0 ? 1 : 0;
}
Run Code Online (Sandbox Code Playgroud)
另外为什么铸造如下:
reinterpret_cast<int>(someValue) = 50;
Run Code Online (Sandbox Code Playgroud)
因错误而被禁止
错误:从类型“bool”到类型“int”的转换无效
(对于以上所有内容,我使用 GCC 5.1 编译器。)
根据http://en.cppreference.com/w/cpp/utility/move
std::move
声明如下:
template <typename T>
std::remove_reference<T>::type&& move(T&& t);
Run Code Online (Sandbox Code Playgroud)
至于我的理解去,当代码为模板,在扣除T
中typename T
失去约的参考信息,所以以下内容:
template <typename T>
void someFunction(T&& value);
Run Code Online (Sandbox Code Playgroud)
使用时如:
int five=5;
someFunction(five);
Run Code Online (Sandbox Code Playgroud)
然后
value
是类型的 int&
T
是 int
要么
const float value = 5.25;
someFunction(value);
Run Code Online (Sandbox Code Playgroud)
然后
value
是类型的 const float&
T
是const float
.如果是这样,那么移动声明中没有必要将返回的类型声明为:
std::remove_reference<T>::type&&
,因为T已经不是引用了.
此外,如果std::move
采用作为参数的引用(实际上1-值参考),然后返回static_cast<T&&>(t)
在std::move
实际上由于参照塌缩将返回-1-参考值或R值的参考,所以它会表现得更像std::forward
不移动.那么什么是诀窍,让它运作正常,我不明白?